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

Side by Side Diff: src/hydrogen.cc

Issue 148503002: A64: Synchronize with r15545. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-bce.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 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
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "hydrogen.h" 28 #include "hydrogen.h"
29 #include "hydrogen-gvn.h"
30 29
31 #include <algorithm> 30 #include <algorithm>
32 31
33 #include "v8.h" 32 #include "v8.h"
34 #include "codegen.h" 33 #include "codegen.h"
35 #include "full-codegen.h" 34 #include "full-codegen.h"
36 #include "hashmap.h" 35 #include "hashmap.h"
36 #include "hydrogen-bce.h"
37 #include "hydrogen-dce.h"
37 #include "hydrogen-environment-liveness.h" 38 #include "hydrogen-environment-liveness.h"
39 #include "hydrogen-escape-analysis.h"
40 #include "hydrogen-infer-representation.h"
41 #include "hydrogen-infer-types.h"
42 #include "hydrogen-gvn.h"
43 #include "hydrogen-osr.h"
44 #include "hydrogen-range-analysis.h"
45 #include "hydrogen-redundant-phi.h"
46 #include "hydrogen-representation-changes.h"
47 #include "hydrogen-sce.h"
48 #include "hydrogen-uint32-analysis.h"
38 #include "lithium-allocator.h" 49 #include "lithium-allocator.h"
39 #include "parser.h" 50 #include "parser.h"
40 #include "scopeinfo.h" 51 #include "scopeinfo.h"
41 #include "scopes.h" 52 #include "scopes.h"
42 #include "stub-cache.h" 53 #include "stub-cache.h"
43 #include "typing.h" 54 #include "typing.h"
44 55
45 #if V8_TARGET_ARCH_IA32 56 #if V8_TARGET_ARCH_IA32
46 #include "ia32/lithium-codegen-ia32.h" 57 #include "ia32/lithium-codegen-ia32.h"
47 #elif V8_TARGET_ARCH_X64 58 #elif V8_TARGET_ARCH_X64
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after
521 } 532 }
522 533
523 int visited_count_; 534 int visited_count_;
524 ZoneList<HBasicBlock*> stack_; 535 ZoneList<HBasicBlock*> stack_;
525 BitVector reachable_; 536 BitVector reachable_;
526 HBasicBlock* dont_visit_; 537 HBasicBlock* dont_visit_;
527 }; 538 };
528 539
529 540
530 void HGraph::Verify(bool do_full_verify) const { 541 void HGraph::Verify(bool do_full_verify) const {
531 Heap::RelocationLock(isolate()->heap()); 542 Heap::RelocationLock relocation_lock(isolate()->heap());
532 AllowHandleDereference allow_deref; 543 AllowHandleDereference allow_deref;
533 AllowDeferredHandleDereference allow_deferred_deref; 544 AllowDeferredHandleDereference allow_deferred_deref;
534 for (int i = 0; i < blocks_.length(); i++) { 545 for (int i = 0; i < blocks_.length(); i++) {
535 HBasicBlock* block = blocks_.at(i); 546 HBasicBlock* block = blocks_.at(i);
536 547
537 block->Verify(); 548 block->Verify();
538 549
539 // Check that every block contains at least one node and that only the last 550 // Check that every block contains at least one node and that only the last
540 // node is a control instruction. 551 // node is a control instruction.
541 HInstruction* current = block->first(); 552 HInstruction* current = block->first();
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
639 #define DEFINE_GET_CONSTANT(Name, name, htype, boolean_value) \ 650 #define DEFINE_GET_CONSTANT(Name, name, htype, boolean_value) \
640 HConstant* HGraph::GetConstant##Name() { \ 651 HConstant* HGraph::GetConstant##Name() { \
641 if (!constant_##name##_.is_set()) { \ 652 if (!constant_##name##_.is_set()) { \
642 HConstant* constant = new(zone()) HConstant( \ 653 HConstant* constant = new(zone()) HConstant( \
643 isolate()->factory()->name##_value(), \ 654 isolate()->factory()->name##_value(), \
644 UniqueValueId(isolate()->heap()->name##_value()), \ 655 UniqueValueId(isolate()->heap()->name##_value()), \
645 Representation::Tagged(), \ 656 Representation::Tagged(), \
646 htype, \ 657 htype, \
647 false, \ 658 false, \
648 true, \ 659 true, \
660 false, \
649 boolean_value); \ 661 boolean_value); \
650 constant->InsertAfter(GetConstantUndefined()); \ 662 constant->InsertAfter(GetConstantUndefined()); \
651 constant_##name##_.set(constant); \ 663 constant_##name##_.set(constant); \
652 } \ 664 } \
653 return constant_##name##_.get(); \ 665 return constant_##name##_.get(); \
654 } 666 }
655 667
656 668
657 DEFINE_GET_CONSTANT(True, true, HType::Boolean(), true) 669 DEFINE_GET_CONSTANT(True, true, HType::Boolean(), true)
658 DEFINE_GET_CONSTANT(False, false, HType::Boolean(), false) 670 DEFINE_GET_CONSTANT(False, false, HType::Boolean(), false)
659 DEFINE_GET_CONSTANT(Hole, the_hole, HType::Tagged(), false) 671 DEFINE_GET_CONSTANT(Hole, the_hole, HType::Tagged(), false)
660 DEFINE_GET_CONSTANT(Null, null, HType::Tagged(), false) 672 DEFINE_GET_CONSTANT(Null, null, HType::Tagged(), false)
661 673
662 674
663 #undef DEFINE_GET_CONSTANT 675 #undef DEFINE_GET_CONSTANT
664 676
665 677
666 HConstant* HGraph::GetInvalidContext() { 678 HConstant* HGraph::GetInvalidContext() {
667 return GetConstant(&constant_invalid_context_, 0xFFFFC0C7); 679 return GetConstant(&constant_invalid_context_, 0xFFFFC0C7);
668 } 680 }
669 681
670 682
683 bool HGraph::IsStandardConstant(HConstant* constant) {
684 if (constant == GetConstantUndefined()) return true;
685 if (constant == GetConstant0()) return true;
686 if (constant == GetConstant1()) return true;
687 if (constant == GetConstantMinus1()) return true;
688 if (constant == GetConstantTrue()) return true;
689 if (constant == GetConstantFalse()) return true;
690 if (constant == GetConstantHole()) return true;
691 if (constant == GetConstantNull()) return true;
692 return false;
693 }
694
695
671 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, int position) 696 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, int position)
672 : builder_(builder), 697 : builder_(builder),
673 position_(position), 698 position_(position),
674 finished_(false), 699 finished_(false),
675 did_then_(false), 700 did_then_(false),
676 did_else_(false), 701 did_else_(false),
677 did_and_(false), 702 did_and_(false),
678 did_or_(false), 703 did_or_(false),
679 captured_(false), 704 captured_(false),
680 needs_compare_(true), 705 needs_compare_(true),
(...skipping 20 matching lines...) Expand all
701 first_true_block_(NULL), 726 first_true_block_(NULL),
702 first_false_block_(NULL), 727 first_false_block_(NULL),
703 split_edge_merge_block_(NULL), 728 split_edge_merge_block_(NULL),
704 merge_block_(NULL) { 729 merge_block_(NULL) {
705 continuation->Continue(&first_true_block_, 730 continuation->Continue(&first_true_block_,
706 &first_false_block_, 731 &first_false_block_,
707 &position_); 732 &position_);
708 } 733 }
709 734
710 735
711 HInstruction* HGraphBuilder::IfBuilder::IfCompare(
712 HValue* left,
713 HValue* right,
714 Token::Value token) {
715 HCompareIDAndBranch* compare =
716 new(zone()) HCompareIDAndBranch(left, right, token);
717 AddCompare(compare);
718 return compare;
719 }
720
721
722 HInstruction* HGraphBuilder::IfBuilder::IfCompareMap(HValue* left,
723 Handle<Map> map) {
724 HCompareMap* compare =
725 new(zone()) HCompareMap(left, map, first_true_block_, first_false_block_);
726 AddCompare(compare);
727 return compare;
728 }
729
730
731 void HGraphBuilder::IfBuilder::AddCompare(HControlInstruction* compare) { 736 void HGraphBuilder::IfBuilder::AddCompare(HControlInstruction* compare) {
732 if (split_edge_merge_block_ != NULL) { 737 if (split_edge_merge_block_ != NULL) {
733 HEnvironment* env = first_false_block_->last_environment(); 738 HEnvironment* env = first_false_block_->last_environment();
734 HBasicBlock* split_edge = 739 HBasicBlock* split_edge =
735 builder_->CreateBasicBlock(env->Copy()); 740 builder_->CreateBasicBlock(env->Copy());
736 if (did_or_) { 741 if (did_or_) {
737 compare->SetSuccessorAt(0, split_edge); 742 compare->SetSuccessorAt(0, split_edge);
738 compare->SetSuccessorAt(1, first_false_block_); 743 compare->SetSuccessorAt(1, first_false_block_);
739 } else { 744 } else {
740 compare->SetSuccessorAt(0, first_true_block_); 745 compare->SetSuccessorAt(0, first_true_block_);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
801 did_then_ = true; 806 did_then_ = true;
802 if (needs_compare_) { 807 if (needs_compare_) {
803 // Handle if's without any expressions, they jump directly to the "else" 808 // Handle if's without any expressions, they jump directly to the "else"
804 // branch. However, we must pretend that the "then" branch is reachable, 809 // branch. However, we must pretend that the "then" branch is reachable,
805 // so that the graph builder visits it and sees any live range extending 810 // so that the graph builder visits it and sees any live range extending
806 // constructs within it. 811 // constructs within it.
807 HConstant* constant_false = builder_->graph()->GetConstantFalse(); 812 HConstant* constant_false = builder_->graph()->GetConstantFalse();
808 ToBooleanStub::Types boolean_type = ToBooleanStub::Types(); 813 ToBooleanStub::Types boolean_type = ToBooleanStub::Types();
809 boolean_type.Add(ToBooleanStub::BOOLEAN); 814 boolean_type.Add(ToBooleanStub::BOOLEAN);
810 HBranch* branch = 815 HBranch* branch =
811 new(zone()) HBranch(constant_false, first_true_block_, 816 new(zone()) HBranch(constant_false, boolean_type, first_true_block_,
812 first_false_block_, boolean_type); 817 first_false_block_);
813 builder_->current_block()->Finish(branch); 818 builder_->current_block()->Finish(branch);
814 } 819 }
815 builder_->set_current_block(first_true_block_); 820 builder_->set_current_block(first_true_block_);
816 } 821 }
817 822
818 823
819 void HGraphBuilder::IfBuilder::Else() { 824 void HGraphBuilder::IfBuilder::Else() {
820 ASSERT(did_then_); 825 ASSERT(did_then_);
821 ASSERT(!captured_); 826 ASSERT(!captured_);
822 ASSERT(!finished_); 827 ASSERT(!finished_);
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
906 builder_->current_block()->GotoNoSimulate(header_block_); 911 builder_->current_block()->GotoNoSimulate(header_block_);
907 912
908 HEnvironment* body_env = env->Copy(); 913 HEnvironment* body_env = env->Copy();
909 HEnvironment* exit_env = env->Copy(); 914 HEnvironment* exit_env = env->Copy();
910 body_block_ = builder_->CreateBasicBlock(body_env); 915 body_block_ = builder_->CreateBasicBlock(body_env);
911 exit_block_ = builder_->CreateBasicBlock(exit_env); 916 exit_block_ = builder_->CreateBasicBlock(exit_env);
912 // Remove the phi from the expression stack 917 // Remove the phi from the expression stack
913 body_env->Pop(); 918 body_env->Pop();
914 919
915 builder_->set_current_block(header_block_); 920 builder_->set_current_block(header_block_);
916 HCompareIDAndBranch* compare = 921 HCompareNumericAndBranch* compare =
917 new(zone()) HCompareIDAndBranch(phi_, terminating, token); 922 new(zone()) HCompareNumericAndBranch(phi_, terminating, token);
918 compare->SetSuccessorAt(0, body_block_); 923 compare->SetSuccessorAt(0, body_block_);
919 compare->SetSuccessorAt(1, exit_block_); 924 compare->SetSuccessorAt(1, exit_block_);
920 builder_->current_block()->Finish(compare); 925 builder_->current_block()->Finish(compare);
921 926
922 builder_->set_current_block(body_block_); 927 builder_->set_current_block(body_block_);
923 if (direction_ == kPreIncrement || direction_ == kPreDecrement) { 928 if (direction_ == kPreIncrement || direction_ == kPreDecrement) {
924 HValue* one = builder_->graph()->GetConstant1(); 929 HValue* one = builder_->graph()->GetConstant1();
925 if (direction_ == kPreIncrement) { 930 if (direction_ == kPreIncrement) {
926 increment_ = HAdd::New(zone(), context_, phi_, one); 931 increment_ = HAdd::New(zone(), context_, phi_, one);
927 } else { 932 } else {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
984 989
985 990
986 void HGraphBuilder::AddSimulate(BailoutId id, 991 void HGraphBuilder::AddSimulate(BailoutId id,
987 RemovableSimulate removable) { 992 RemovableSimulate removable) {
988 ASSERT(current_block() != NULL); 993 ASSERT(current_block() != NULL);
989 ASSERT(no_side_effects_scope_count_ == 0); 994 ASSERT(no_side_effects_scope_count_ == 0);
990 current_block()->AddSimulate(id, removable); 995 current_block()->AddSimulate(id, removable);
991 } 996 }
992 997
993 998
994 HBoundsCheck* HGraphBuilder::AddBoundsCheck(HValue* index, HValue* length) {
995 HBoundsCheck* result = new(graph()->zone()) HBoundsCheck(index, length);
996 AddInstruction(result);
997 return result;
998 }
999
1000
1001 HReturn* HGraphBuilder::AddReturn(HValue* value) { 999 HReturn* HGraphBuilder::AddReturn(HValue* value) {
1002 HValue* context = environment()->LookupContext(); 1000 HValue* context = environment()->LookupContext();
1003 int num_parameters = graph()->info()->num_parameters(); 1001 int num_parameters = graph()->info()->num_parameters();
1004 HValue* params = AddInstruction(new(graph()->zone()) 1002 HValue* params = Add<HConstant>(num_parameters);
1005 HConstant(num_parameters));
1006 HReturn* return_instruction = new(graph()->zone()) 1003 HReturn* return_instruction = new(graph()->zone())
1007 HReturn(value, context, params); 1004 HReturn(value, context, params);
1008 current_block()->FinishExit(return_instruction); 1005 current_block()->FinishExit(return_instruction);
1009 return return_instruction; 1006 return return_instruction;
1010 } 1007 }
1011 1008
1012 1009
1010 void HGraphBuilder::AddSoftDeoptimize(SoftDeoptimizeMode mode) {
1011 isolate()->counters()->soft_deopts_requested()->Increment();
1012 if (FLAG_always_opt && mode == CAN_OMIT_SOFT_DEOPT) return;
1013 if (current_block()->IsDeoptimizing()) return;
1014 Add<HSoftDeoptimize>();
1015 isolate()->counters()->soft_deopts_inserted()->Increment();
1016 current_block()->MarkAsDeoptimizing();
1017 graph()->set_has_soft_deoptimize(true);
1018 }
1019
1020
1013 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { 1021 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
1014 HBasicBlock* b = graph()->CreateBasicBlock(); 1022 HBasicBlock* b = graph()->CreateBasicBlock();
1015 b->SetInitialEnvironment(env); 1023 b->SetInitialEnvironment(env);
1016 return b; 1024 return b;
1017 } 1025 }
1018 1026
1019 1027
1020 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { 1028 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
1021 HBasicBlock* header = graph()->CreateBasicBlock(); 1029 HBasicBlock* header = graph()->CreateBasicBlock();
1022 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); 1030 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
1023 header->SetInitialEnvironment(entry_env); 1031 header->SetInitialEnvironment(entry_env);
1024 header->AttachLoopInformation(); 1032 header->AttachLoopInformation();
1025 return header; 1033 return header;
1026 } 1034 }
1027 1035
1028 1036
1029 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { 1037 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) {
1030 if (obj->type().IsHeapObject()) return obj; 1038 if (obj->type().IsHeapObject()) return obj;
1031 HCheckHeapObject* check = new(zone()) HCheckHeapObject(obj); 1039 return Add<HCheckHeapObject>(obj);
1032 AddInstruction(check);
1033 return check;
1034 } 1040 }
1035 1041
1036 1042
1037 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, 1043 HValue* HGraphBuilder::BuildCheckMap(HValue* obj,
1038 Handle<Map> map) { 1044 Handle<Map> map) {
1039 HCheckMaps* check = HCheckMaps::New(obj, map, zone()); 1045 HCheckMaps* check = HCheckMaps::New(obj, map, zone());
1040 AddInstruction(check); 1046 AddInstruction(check);
1041 return check; 1047 return check;
1042 } 1048 }
1043 1049
1044 1050
1045 HInstruction* HGraphBuilder::BuildExternalArrayElementAccess( 1051 HInstruction* HGraphBuilder::BuildExternalArrayElementAccess(
1046 HValue* external_elements, 1052 HValue* external_elements,
1047 HValue* checked_key, 1053 HValue* checked_key,
1048 HValue* val, 1054 HValue* val,
1049 HValue* dependency, 1055 HValue* dependency,
1050 ElementsKind elements_kind, 1056 ElementsKind elements_kind,
1051 bool is_store) { 1057 bool is_store) {
1052 Zone* zone = this->zone(); 1058 Zone* zone = this->zone();
1053 if (is_store) { 1059 if (is_store) {
1054 ASSERT(val != NULL); 1060 ASSERT(val != NULL);
1055 switch (elements_kind) { 1061 switch (elements_kind) {
1056 case EXTERNAL_PIXEL_ELEMENTS: { 1062 case EXTERNAL_PIXEL_ELEMENTS: {
1057 val = AddInstruction(new(zone) HClampToUint8(val)); 1063 val = Add<HClampToUint8>(val);
1058 break; 1064 break;
1059 } 1065 }
1060 case EXTERNAL_BYTE_ELEMENTS: 1066 case EXTERNAL_BYTE_ELEMENTS:
1061 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 1067 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
1062 case EXTERNAL_SHORT_ELEMENTS: 1068 case EXTERNAL_SHORT_ELEMENTS:
1063 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 1069 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
1064 case EXTERNAL_INT_ELEMENTS: 1070 case EXTERNAL_INT_ELEMENTS:
1065 case EXTERNAL_UNSIGNED_INT_ELEMENTS: { 1071 case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
1066 break; 1072 break;
1067 } 1073 }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1131 1137
1132 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, 1138 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
1133 HValue* elements, 1139 HValue* elements,
1134 ElementsKind kind, 1140 ElementsKind kind,
1135 HValue* length, 1141 HValue* length,
1136 HValue* key, 1142 HValue* key,
1137 bool is_js_array) { 1143 bool is_js_array) {
1138 Zone* zone = this->zone(); 1144 Zone* zone = this->zone();
1139 IfBuilder length_checker(this); 1145 IfBuilder length_checker(this);
1140 1146
1141 length_checker.IfCompare(length, key, Token::EQ); 1147 length_checker.If<HCompareNumericAndBranch>(length, key, Token::EQ);
1142 length_checker.Then(); 1148 length_checker.Then();
1143 1149
1144 HValue* current_capacity = 1150 HValue* current_capacity = AddLoadFixedArrayLength(elements);
1145 AddInstruction(new(zone) HFixedArrayBaseLength(elements));
1146 1151
1147 IfBuilder capacity_checker(this); 1152 IfBuilder capacity_checker(this);
1148 1153
1149 capacity_checker.IfCompare(length, current_capacity, Token::EQ); 1154 capacity_checker.If<HCompareNumericAndBranch>(length, current_capacity,
1155 Token::EQ);
1150 capacity_checker.Then(); 1156 capacity_checker.Then();
1151 1157
1152 HValue* context = environment()->LookupContext(); 1158 HValue* context = environment()->LookupContext();
1153 1159
1154 HValue* new_capacity = 1160 HValue* new_capacity =
1155 BuildNewElementsCapacity(context, current_capacity); 1161 BuildNewElementsCapacity(context, current_capacity);
1156 1162
1157 HValue* new_elements = BuildGrowElementsCapacity(object, elements, 1163 HValue* new_elements = BuildGrowElementsCapacity(object, elements,
1158 kind, length, 1164 kind, length,
1159 new_capacity); 1165 new_capacity);
(...skipping 10 matching lines...) Expand all
1170 new_length->ClearFlag(HValue::kCanOverflow); 1176 new_length->ClearFlag(HValue::kCanOverflow);
1171 1177
1172 Representation representation = IsFastElementsKind(kind) 1178 Representation representation = IsFastElementsKind(kind)
1173 ? Representation::Smi() : Representation::Tagged(); 1179 ? Representation::Smi() : Representation::Tagged();
1174 AddStore(object, HObjectAccess::ForArrayLength(), new_length, 1180 AddStore(object, HObjectAccess::ForArrayLength(), new_length,
1175 representation); 1181 representation);
1176 } 1182 }
1177 1183
1178 length_checker.Else(); 1184 length_checker.Else();
1179 1185
1180 AddBoundsCheck(key, length); 1186 Add<HBoundsCheck>(key, length);
1181 environment()->Push(elements); 1187 environment()->Push(elements);
1182 1188
1183 length_checker.End(); 1189 length_checker.End();
1184 1190
1185 return environment()->Pop(); 1191 return environment()->Pop();
1186 } 1192 }
1187 1193
1188 1194
1189 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object, 1195 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object,
1190 HValue* elements, 1196 HValue* elements,
1191 ElementsKind kind, 1197 ElementsKind kind,
1192 HValue* length) { 1198 HValue* length) {
1193 Zone* zone = this->zone(); 1199 Factory* factory = isolate()->factory();
1194 Heap* heap = isolate()->heap();
1195 1200
1196 IfBuilder cow_checker(this); 1201 IfBuilder cow_checker(this);
1197 1202
1198 cow_checker.IfCompareMap(elements, 1203 cow_checker.If<HCompareMap>(elements, factory->fixed_cow_array_map());
1199 Handle<Map>(heap->fixed_cow_array_map()));
1200 cow_checker.Then(); 1204 cow_checker.Then();
1201 1205
1202 HValue* capacity = 1206 HValue* capacity = AddLoadFixedArrayLength(elements);
1203 AddInstruction(new(zone) HFixedArrayBaseLength(elements));
1204 1207
1205 HValue* new_elements = BuildGrowElementsCapacity(object, elements, 1208 HValue* new_elements = BuildGrowElementsCapacity(object, elements,
1206 kind, length, capacity); 1209 kind, length, capacity);
1207 1210
1208 environment()->Push(new_elements); 1211 environment()->Push(new_elements);
1209 1212
1210 cow_checker.Else(); 1213 cow_checker.Else();
1211 1214
1212 environment()->Push(elements); 1215 environment()->Push(elements);
1213 1216
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1248 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { 1251 store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
1249 HCheckMaps* check_cow_map = HCheckMaps::New( 1252 HCheckMaps* check_cow_map = HCheckMaps::New(
1250 elements, isolate()->factory()->fixed_array_map(), zone); 1253 elements, isolate()->factory()->fixed_array_map(), zone);
1251 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); 1254 check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
1252 AddInstruction(check_cow_map); 1255 AddInstruction(check_cow_map);
1253 } 1256 }
1254 HInstruction* length = NULL; 1257 HInstruction* length = NULL;
1255 if (is_js_array) { 1258 if (is_js_array) {
1256 length = AddLoad(object, HObjectAccess::ForArrayLength(), mapcheck, 1259 length = AddLoad(object, HObjectAccess::ForArrayLength(), mapcheck,
1257 Representation::Smi()); 1260 Representation::Smi());
1258 length->set_type(HType::Smi());
1259 } else { 1261 } else {
1260 length = AddInstruction(new(zone) HFixedArrayBaseLength(elements)); 1262 length = AddLoadFixedArrayLength(elements);
1261 } 1263 }
1264 length->set_type(HType::Smi());
1262 HValue* checked_key = NULL; 1265 HValue* checked_key = NULL;
1263 if (IsExternalArrayElementsKind(elements_kind)) { 1266 if (IsExternalArrayElementsKind(elements_kind)) {
1264 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { 1267 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
1265 NoObservableSideEffectsScope no_effects(this); 1268 NoObservableSideEffectsScope no_effects(this);
1266 HLoadExternalArrayPointer* external_elements = 1269 HLoadExternalArrayPointer* external_elements =
1267 new(zone) HLoadExternalArrayPointer(elements); 1270 Add<HLoadExternalArrayPointer>(elements);
1268 AddInstruction(external_elements);
1269 IfBuilder length_checker(this); 1271 IfBuilder length_checker(this);
1270 length_checker.IfCompare(key, length, Token::LT); 1272 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT);
1271 length_checker.Then(); 1273 length_checker.Then();
1272 IfBuilder negative_checker(this); 1274 IfBuilder negative_checker(this);
1273 HValue* bounds_check = negative_checker.IfCompare( 1275 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>(
1274 key, graph()->GetConstant0(), Token::GTE); 1276 key, graph()->GetConstant0(), Token::GTE);
1275 negative_checker.Then(); 1277 negative_checker.Then();
1276 HInstruction* result = BuildExternalArrayElementAccess( 1278 HInstruction* result = BuildExternalArrayElementAccess(
1277 external_elements, key, val, bounds_check, 1279 external_elements, key, val, bounds_check,
1278 elements_kind, is_store); 1280 elements_kind, is_store);
1279 AddInstruction(result); 1281 AddInstruction(result);
1280 negative_checker.ElseDeopt(); 1282 negative_checker.ElseDeopt();
1281 length_checker.End(); 1283 length_checker.End();
1282 return result; 1284 return result;
1283 } else { 1285 } else {
1284 ASSERT(store_mode == STANDARD_STORE); 1286 ASSERT(store_mode == STANDARD_STORE);
1285 checked_key = AddBoundsCheck(key, length); 1287 checked_key = Add<HBoundsCheck>(key, length);
1286 HLoadExternalArrayPointer* external_elements = 1288 HLoadExternalArrayPointer* external_elements =
1287 new(zone) HLoadExternalArrayPointer(elements); 1289 Add<HLoadExternalArrayPointer>(elements);
1288 AddInstruction(external_elements);
1289 return AddInstruction(BuildExternalArrayElementAccess( 1290 return AddInstruction(BuildExternalArrayElementAccess(
1290 external_elements, checked_key, val, mapcheck, 1291 external_elements, checked_key, val, mapcheck,
1291 elements_kind, is_store)); 1292 elements_kind, is_store));
1292 } 1293 }
1293 } 1294 }
1294 ASSERT(fast_smi_only_elements || 1295 ASSERT(fast_smi_only_elements ||
1295 fast_elements || 1296 fast_elements ||
1296 IsFastDoubleElementsKind(elements_kind)); 1297 IsFastDoubleElementsKind(elements_kind));
1297 1298
1298 // In case val is stored into a fast smi array, assure that the value is a smi 1299 // In case val is stored into a fast smi array, assure that the value is a smi
1299 // before manipulating the backing store. Otherwise the actual store may 1300 // before manipulating the backing store. Otherwise the actual store may
1300 // deopt, leaving the backing store in an invalid state. 1301 // deopt, leaving the backing store in an invalid state.
1301 if (is_store && IsFastSmiElementsKind(elements_kind) && 1302 if (is_store && IsFastSmiElementsKind(elements_kind) &&
1302 !val->type().IsSmi()) { 1303 !val->type().IsSmi()) {
1303 val = AddInstruction(new(zone) HForceRepresentation( 1304 val = Add<HForceRepresentation>(val, Representation::Smi());
1304 val, Representation::Smi()));
1305 } 1305 }
1306 1306
1307 if (IsGrowStoreMode(store_mode)) { 1307 if (IsGrowStoreMode(store_mode)) {
1308 NoObservableSideEffectsScope no_effects(this); 1308 NoObservableSideEffectsScope no_effects(this);
1309 elements = BuildCheckForCapacityGrow(object, elements, elements_kind, 1309 elements = BuildCheckForCapacityGrow(object, elements, elements_kind,
1310 length, key, is_js_array); 1310 length, key, is_js_array);
1311 checked_key = key; 1311 checked_key = key;
1312 } else { 1312 } else {
1313 checked_key = AddBoundsCheck(key, length); 1313 checked_key = Add<HBoundsCheck>(key, length);
1314 1314
1315 if (is_store && (fast_elements || fast_smi_only_elements)) { 1315 if (is_store && (fast_elements || fast_smi_only_elements)) {
1316 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { 1316 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
1317 NoObservableSideEffectsScope no_effects(this); 1317 NoObservableSideEffectsScope no_effects(this);
1318 1318
1319 elements = BuildCopyElementsOnWrite(object, elements, elements_kind, 1319 elements = BuildCopyElementsOnWrite(object, elements, elements_kind,
1320 length); 1320 length);
1321 } else { 1321 } else {
1322 HCheckMaps* check_cow_map = HCheckMaps::New( 1322 HCheckMaps* check_cow_map = HCheckMaps::New(
1323 elements, isolate()->factory()->fixed_array_map(), zone); 1323 elements, isolate()->factory()->fixed_array_map(), zone);
1324 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); 1324 check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
1325 AddInstruction(check_cow_map); 1325 AddInstruction(check_cow_map);
1326 } 1326 }
1327 } 1327 }
1328 } 1328 }
1329 return AddInstruction( 1329 return AddInstruction(
1330 BuildFastElementAccess(elements, checked_key, val, mapcheck, 1330 BuildFastElementAccess(elements, checked_key, val, mapcheck,
1331 elements_kind, is_store, load_mode, store_mode)); 1331 elements_kind, is_store, load_mode, store_mode));
1332 } 1332 }
1333 1333
1334 1334
1335 HValue* HGraphBuilder::BuildAllocateElements(HValue* context, 1335 HValue* HGraphBuilder::BuildAllocateElements(HValue* context,
1336 ElementsKind kind, 1336 ElementsKind kind,
1337 HValue* capacity) { 1337 HValue* capacity) {
1338 Zone* zone = this->zone(); 1338 Zone* zone = this->zone();
1339 1339
1340 int elements_size = IsFastDoubleElementsKind(kind) 1340 int elements_size = IsFastDoubleElementsKind(kind)
1341 ? kDoubleSize : kPointerSize; 1341 ? kDoubleSize : kPointerSize;
1342 HConstant* elements_size_value = new(zone) HConstant(elements_size); 1342 HConstant* elements_size_value = Add<HConstant>(elements_size);
1343 AddInstruction(elements_size_value);
1344 HValue* mul = AddInstruction( 1343 HValue* mul = AddInstruction(
1345 HMul::New(zone, context, capacity, elements_size_value)); 1344 HMul::New(zone, context, capacity, elements_size_value));
1346 mul->ClearFlag(HValue::kCanOverflow); 1345 mul->ClearFlag(HValue::kCanOverflow);
1347 1346
1348 HConstant* header_size = new(zone) HConstant(FixedArray::kHeaderSize); 1347 HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize);
1349 AddInstruction(header_size);
1350 HValue* total_size = AddInstruction( 1348 HValue* total_size = AddInstruction(
1351 HAdd::New(zone, context, mul, header_size)); 1349 HAdd::New(zone, context, mul, header_size));
1352 total_size->ClearFlag(HValue::kCanOverflow); 1350 total_size->ClearFlag(HValue::kCanOverflow);
1353 1351
1354 HAllocate::Flags flags = HAllocate::DefaultFlags(kind); 1352 HAllocate::Flags flags = HAllocate::DefaultFlags(kind);
1355 if (isolate()->heap()->ShouldGloballyPretenure()) { 1353 if (isolate()->heap()->ShouldGloballyPretenure()) {
1356 // TODO(hpayer): When pretenuring can be internalized, flags can become 1354 // TODO(hpayer): When pretenuring can be internalized, flags can become
1357 // private to HAllocate. 1355 // private to HAllocate.
1358 if (IsFastDoubleElementsKind(kind)) { 1356 if (IsFastDoubleElementsKind(kind)) {
1359 flags = static_cast<HAllocate::Flags>( 1357 flags = static_cast<HAllocate::Flags>(
1360 flags | HAllocate::CAN_ALLOCATE_IN_OLD_DATA_SPACE); 1358 flags | HAllocate::CAN_ALLOCATE_IN_OLD_DATA_SPACE);
1361 } else { 1359 } else {
1362 flags = static_cast<HAllocate::Flags>( 1360 flags = static_cast<HAllocate::Flags>(
1363 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); 1361 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE);
1364 } 1362 }
1365 } 1363 }
1366 1364
1367 HValue* elements = 1365 return Add<HAllocate>(context, total_size, HType::JSArray(), flags);
1368 AddInstruction(new(zone) HAllocate(context, total_size,
1369 HType::JSArray(), flags));
1370 return elements;
1371 } 1366 }
1372 1367
1373 1368
1374 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements, 1369 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements,
1375 ElementsKind kind, 1370 ElementsKind kind,
1376 HValue* capacity) { 1371 HValue* capacity) {
1377 Factory* factory = isolate()->factory(); 1372 Factory* factory = isolate()->factory();
1378 Handle<Map> map = IsFastDoubleElementsKind(kind) 1373 Handle<Map> map = IsFastDoubleElementsKind(kind)
1379 ? factory->fixed_double_array_map() 1374 ? factory->fixed_double_array_map()
1380 : factory->fixed_array_map(); 1375 : factory->fixed_array_map();
(...skipping 18 matching lines...) Expand all
1399 1394
1400 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array, 1395 HInnerAllocatedObject* HGraphBuilder::BuildJSArrayHeader(HValue* array,
1401 HValue* array_map, 1396 HValue* array_map,
1402 AllocationSiteMode mode, 1397 AllocationSiteMode mode,
1403 HValue* allocation_site_payload, 1398 HValue* allocation_site_payload,
1404 HValue* length_field) { 1399 HValue* length_field) {
1405 1400
1406 AddStore(array, HObjectAccess::ForMap(), array_map); 1401 AddStore(array, HObjectAccess::ForMap(), array_map);
1407 1402
1408 HConstant* empty_fixed_array = 1403 HConstant* empty_fixed_array =
1409 new(zone()) HConstant(isolate()->factory()->empty_fixed_array()); 1404 Add<HConstant>(isolate()->factory()->empty_fixed_array());
1410 AddInstruction(empty_fixed_array);
1411 1405
1412 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); 1406 HObjectAccess access = HObjectAccess::ForPropertiesPointer();
1413 AddStore(array, access, empty_fixed_array); 1407 AddStore(array, access, empty_fixed_array);
1414 AddStore(array, HObjectAccess::ForArrayLength(), length_field); 1408 AddStore(array, HObjectAccess::ForArrayLength(), length_field);
1415 1409
1416 if (mode == TRACK_ALLOCATION_SITE) { 1410 if (mode == TRACK_ALLOCATION_SITE) {
1417 BuildCreateAllocationSiteInfo(array, 1411 BuildCreateAllocationSiteInfo(array,
1418 JSArray::kSize, 1412 JSArray::kSize,
1419 allocation_site_payload); 1413 allocation_site_payload);
1420 } 1414 }
1421 1415
1422 int elements_location = JSArray::kSize; 1416 int elements_location = JSArray::kSize;
1423 if (mode == TRACK_ALLOCATION_SITE) { 1417 if (mode == TRACK_ALLOCATION_SITE) {
1424 elements_location += AllocationSiteInfo::kSize; 1418 elements_location += AllocationSiteInfo::kSize;
1425 } 1419 }
1426 1420
1427 HInnerAllocatedObject* elements = new(zone()) HInnerAllocatedObject( 1421 HInnerAllocatedObject* elements =
1428 array, elements_location); 1422 Add<HInnerAllocatedObject>(array, elements_location);
1429 AddInstruction(elements);
1430
1431 AddStore(array, HObjectAccess::ForElementsPointer(), elements); 1423 AddStore(array, HObjectAccess::ForElementsPointer(), elements);
1432 return elements; 1424 return elements;
1433 } 1425 }
1434 1426
1435 1427
1436 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object, 1428 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object,
1437 HValue* typecheck) { 1429 HValue* typecheck) {
1438 return AddLoad(object, HObjectAccess::ForElementsPointer(), typecheck); 1430 return AddLoad(object, HObjectAccess::ForElementsPointer(), typecheck);
1439 } 1431 }
1440 1432
1441 1433
1434 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(HValue* object) {
1435 HLoadNamedField* instr = AddLoad(object, HObjectAccess::ForFixedArrayLength(),
1436 NULL, Representation::Smi());
1437 instr->set_type(HType::Smi());
1438 return instr;
1439 }
1440
1441
1442 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context, 1442 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* context,
1443 HValue* old_capacity) { 1443 HValue* old_capacity) {
1444 Zone* zone = this->zone(); 1444 Zone* zone = this->zone();
1445 HValue* half_old_capacity = 1445 HValue* half_old_capacity =
1446 AddInstruction(HShr::New(zone, context, old_capacity, 1446 AddInstruction(HShr::New(zone, context, old_capacity,
1447 graph_->GetConstant1())); 1447 graph_->GetConstant1()));
1448 half_old_capacity->ClearFlag(HValue::kCanOverflow); 1448 half_old_capacity->ClearFlag(HValue::kCanOverflow);
1449 1449
1450 HValue* new_capacity = AddInstruction( 1450 HValue* new_capacity = AddInstruction(
1451 HAdd::New(zone, context, half_old_capacity, old_capacity)); 1451 HAdd::New(zone, context, half_old_capacity, old_capacity));
1452 new_capacity->ClearFlag(HValue::kCanOverflow); 1452 new_capacity->ClearFlag(HValue::kCanOverflow);
1453 1453
1454 HValue* min_growth = AddInstruction(new(zone) HConstant(16)); 1454 HValue* min_growth = Add<HConstant>(16);
1455 1455
1456 new_capacity = AddInstruction( 1456 new_capacity = AddInstruction(
1457 HAdd::New(zone, context, new_capacity, min_growth)); 1457 HAdd::New(zone, context, new_capacity, min_growth));
1458 new_capacity->ClearFlag(HValue::kCanOverflow); 1458 new_capacity->ClearFlag(HValue::kCanOverflow);
1459 1459
1460 return new_capacity; 1460 return new_capacity;
1461 } 1461 }
1462 1462
1463 1463
1464 void HGraphBuilder::BuildNewSpaceArrayCheck(HValue* length, ElementsKind kind) { 1464 void HGraphBuilder::BuildNewSpaceArrayCheck(HValue* length, ElementsKind kind) {
1465 Zone* zone = this->zone();
1466 Heap* heap = isolate()->heap(); 1465 Heap* heap = isolate()->heap();
1467 int element_size = IsFastDoubleElementsKind(kind) ? kDoubleSize 1466 int element_size = IsFastDoubleElementsKind(kind) ? kDoubleSize
1468 : kPointerSize; 1467 : kPointerSize;
1469 int max_size = heap->MaxRegularSpaceAllocationSize() / element_size; 1468 int max_size = heap->MaxRegularSpaceAllocationSize() / element_size;
1470 max_size -= JSArray::kSize / element_size; 1469 max_size -= JSArray::kSize / element_size;
1471 HConstant* max_size_constant = new(zone) HConstant(max_size); 1470 HConstant* max_size_constant = Add<HConstant>(max_size);
1472 AddInstruction(max_size_constant);
1473 // Since we're forcing Integer32 representation for this HBoundsCheck, 1471 // Since we're forcing Integer32 representation for this HBoundsCheck,
1474 // there's no need to Smi-check the index. 1472 // there's no need to Smi-check the index.
1475 AddInstruction(new(zone) HBoundsCheck(length, max_size_constant)); 1473 Add<HBoundsCheck>(length, max_size_constant);
1476 } 1474 }
1477 1475
1478 1476
1479 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, 1477 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
1480 HValue* elements, 1478 HValue* elements,
1481 ElementsKind kind, 1479 ElementsKind kind,
1482 HValue* length, 1480 HValue* length,
1483 HValue* new_capacity) { 1481 HValue* new_capacity) {
1484 HValue* context = environment()->LookupContext(); 1482 HValue* context = environment()->LookupContext();
1485 1483
(...skipping 15 matching lines...) Expand all
1501 void HGraphBuilder::BuildFillElementsWithHole(HValue* context, 1499 void HGraphBuilder::BuildFillElementsWithHole(HValue* context,
1502 HValue* elements, 1500 HValue* elements,
1503 ElementsKind elements_kind, 1501 ElementsKind elements_kind,
1504 HValue* from, 1502 HValue* from,
1505 HValue* to) { 1503 HValue* to) {
1506 // Fast elements kinds need to be initialized in case statements below cause 1504 // Fast elements kinds need to be initialized in case statements below cause
1507 // a garbage collection. 1505 // a garbage collection.
1508 Factory* factory = isolate()->factory(); 1506 Factory* factory = isolate()->factory();
1509 1507
1510 double nan_double = FixedDoubleArray::hole_nan_as_double(); 1508 double nan_double = FixedDoubleArray::hole_nan_as_double();
1511 Zone* zone = this->zone();
1512 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) 1509 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
1513 ? AddInstruction(new(zone) HConstant(factory->the_hole_value())) 1510 ? Add<HConstant>(factory->the_hole_value())
1514 : AddInstruction(new(zone) HConstant(nan_double)); 1511 : Add<HConstant>(nan_double);
1515 1512
1516 // Special loop unfolding case 1513 // Special loop unfolding case
1517 static const int kLoopUnfoldLimit = 4; 1514 static const int kLoopUnfoldLimit = 4;
1518 bool unfold_loop = false; 1515 bool unfold_loop = false;
1519 int initial_capacity = JSArray::kPreallocatedArrayElements; 1516 int initial_capacity = JSArray::kPreallocatedArrayElements;
1520 if (from->IsConstant() && to->IsConstant() && 1517 if (from->IsConstant() && to->IsConstant() &&
1521 initial_capacity <= kLoopUnfoldLimit) { 1518 initial_capacity <= kLoopUnfoldLimit) {
1522 HConstant* constant_from = HConstant::cast(from); 1519 HConstant* constant_from = HConstant::cast(from);
1523 HConstant* constant_to = HConstant::cast(to); 1520 HConstant* constant_to = HConstant::cast(to);
1524 1521
1525 if (constant_from->HasInteger32Value() && 1522 if (constant_from->HasInteger32Value() &&
1526 constant_from->Integer32Value() == 0 && 1523 constant_from->Integer32Value() == 0 &&
1527 constant_to->HasInteger32Value() && 1524 constant_to->HasInteger32Value() &&
1528 constant_to->Integer32Value() == initial_capacity) { 1525 constant_to->Integer32Value() == initial_capacity) {
1529 unfold_loop = true; 1526 unfold_loop = true;
1530 } 1527 }
1531 } 1528 }
1532 1529
1533 // Since we're about to store a hole value, the store instruction below must 1530 // Since we're about to store a hole value, the store instruction below must
1534 // assume an elements kind that supports heap object values. 1531 // assume an elements kind that supports heap object values.
1535 if (IsFastSmiOrObjectElementsKind(elements_kind)) { 1532 if (IsFastSmiOrObjectElementsKind(elements_kind)) {
1536 elements_kind = FAST_HOLEY_ELEMENTS; 1533 elements_kind = FAST_HOLEY_ELEMENTS;
1537 } 1534 }
1538 1535
1539 if (unfold_loop) { 1536 if (unfold_loop) {
1540 for (int i = 0; i < initial_capacity; i++) { 1537 for (int i = 0; i < initial_capacity; i++) {
1541 HInstruction* key = AddInstruction(new(zone) HConstant(i)); 1538 HInstruction* key = Add<HConstant>(i);
1542 AddInstruction(new(zone) HStoreKeyed(elements, key, hole, elements_kind)); 1539 Add<HStoreKeyed>(elements, key, hole, elements_kind);
1543 } 1540 }
1544 } else { 1541 } else {
1545 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement); 1542 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement);
1546 1543
1547 HValue* key = builder.BeginBody(from, to, Token::LT); 1544 HValue* key = builder.BeginBody(from, to, Token::LT);
1548 1545
1549 AddInstruction(new(zone) HStoreKeyed(elements, key, hole, elements_kind)); 1546 Add<HStoreKeyed>(elements, key, hole, elements_kind);
1550 1547
1551 builder.EndBody(); 1548 builder.EndBody();
1552 } 1549 }
1553 } 1550 }
1554 1551
1555 1552
1556 void HGraphBuilder::BuildCopyElements(HValue* context, 1553 void HGraphBuilder::BuildCopyElements(HValue* context,
1557 HValue* from_elements, 1554 HValue* from_elements,
1558 ElementsKind from_elements_kind, 1555 ElementsKind from_elements_kind,
1559 HValue* to_elements, 1556 HValue* to_elements,
1560 ElementsKind to_elements_kind, 1557 ElementsKind to_elements_kind,
1561 HValue* length, 1558 HValue* length,
1562 HValue* capacity) { 1559 HValue* capacity) {
1563 bool pre_fill_with_holes = 1560 bool pre_fill_with_holes =
1564 IsFastDoubleElementsKind(from_elements_kind) && 1561 IsFastDoubleElementsKind(from_elements_kind) &&
1565 IsFastObjectElementsKind(to_elements_kind); 1562 IsFastObjectElementsKind(to_elements_kind);
1566 1563
1567 if (pre_fill_with_holes) { 1564 if (pre_fill_with_holes) {
1568 // If the copy might trigger a GC, make sure that the FixedArray is 1565 // If the copy might trigger a GC, make sure that the FixedArray is
1569 // pre-initialized with holes to make sure that it's always in a consistent 1566 // pre-initialized with holes to make sure that it's always in a consistent
1570 // state. 1567 // state.
1571 BuildFillElementsWithHole(context, to_elements, to_elements_kind, 1568 BuildFillElementsWithHole(context, to_elements, to_elements_kind,
1572 graph()->GetConstant0(), capacity); 1569 graph()->GetConstant0(), capacity);
1573 } 1570 }
1574 1571
1575 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement); 1572 LoopBuilder builder(this, context, LoopBuilder::kPostIncrement);
1576 1573
1577 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT); 1574 HValue* key = builder.BeginBody(graph()->GetConstant0(), length, Token::LT);
1578 1575
1579 HValue* element = 1576 HValue* element = Add<HLoadKeyed>(from_elements, key,
1580 AddInstruction(new(zone()) HLoadKeyed(from_elements, key, NULL, 1577 static_cast<HValue*>(NULL),
1581 from_elements_kind, 1578 from_elements_kind,
1582 ALLOW_RETURN_HOLE)); 1579 ALLOW_RETURN_HOLE);
1583 1580
1584 ElementsKind holey_kind = IsFastSmiElementsKind(to_elements_kind) 1581 ElementsKind holey_kind = IsFastSmiElementsKind(to_elements_kind)
1585 ? FAST_HOLEY_ELEMENTS : to_elements_kind; 1582 ? FAST_HOLEY_ELEMENTS : to_elements_kind;
1586 HInstruction* holey_store = AddInstruction( 1583 HInstruction* holey_store = Add<HStoreKeyed>(to_elements, key,
1587 new(zone()) HStoreKeyed(to_elements, key, element, holey_kind)); 1584 element, holey_kind);
1588 // Allow NaN hole values to converted to their tagged counterparts. 1585 // Allow NaN hole values to converted to their tagged counterparts.
1589 if (IsFastHoleyElementsKind(to_elements_kind)) { 1586 if (IsFastHoleyElementsKind(to_elements_kind)) {
1590 holey_store->SetFlag(HValue::kAllowUndefinedAsNaN); 1587 holey_store->SetFlag(HValue::kAllowUndefinedAsNaN);
1591 } 1588 }
1592 1589
1593 builder.EndBody(); 1590 builder.EndBody();
1594 1591
1595 if (!pre_fill_with_holes && length != capacity) { 1592 if (!pre_fill_with_holes && length != capacity) {
1596 // Fill unused capacity with the hole. 1593 // Fill unused capacity with the hole.
1597 BuildFillElementsWithHole(context, to_elements, to_elements_kind, 1594 BuildFillElementsWithHole(context, to_elements, to_elements_kind,
1598 key, capacity); 1595 key, capacity);
1599 } 1596 }
1600 } 1597 }
1601 1598
1602 1599
1603 HValue* HGraphBuilder::BuildCloneShallowArray(HContext* context, 1600 HValue* HGraphBuilder::BuildCloneShallowArray(HContext* context,
1604 HValue* boilerplate, 1601 HValue* boilerplate,
1602 HValue* allocation_site,
1605 AllocationSiteMode mode, 1603 AllocationSiteMode mode,
1606 ElementsKind kind, 1604 ElementsKind kind,
1607 int length) { 1605 int length) {
1608 Zone* zone = this->zone();
1609
1610 NoObservableSideEffectsScope no_effects(this); 1606 NoObservableSideEffectsScope no_effects(this);
1611 1607
1612 // All sizes here are multiples of kPointerSize. 1608 // All sizes here are multiples of kPointerSize.
1613 int size = JSArray::kSize; 1609 int size = JSArray::kSize;
1614 if (mode == TRACK_ALLOCATION_SITE) { 1610 if (mode == TRACK_ALLOCATION_SITE) {
1615 size += AllocationSiteInfo::kSize; 1611 size += AllocationSiteInfo::kSize;
1616 } 1612 }
1617 int elems_offset = size; 1613 int elems_offset = size;
1618 if (length > 0) { 1614 if (length > 0) {
1619 size += IsFastDoubleElementsKind(kind) 1615 size += IsFastDoubleElementsKind(kind)
1620 ? FixedDoubleArray::SizeFor(length) 1616 ? FixedDoubleArray::SizeFor(length)
1621 : FixedArray::SizeFor(length); 1617 : FixedArray::SizeFor(length);
1622 } 1618 }
1623 1619
1624 HAllocate::Flags allocate_flags = HAllocate::DefaultFlags(kind); 1620 HAllocate::Flags allocate_flags = HAllocate::DefaultFlags(kind);
1625 // Allocate both the JS array and the elements array in one big 1621 // Allocate both the JS array and the elements array in one big
1626 // allocation. This avoids multiple limit checks. 1622 // allocation. This avoids multiple limit checks.
1627 HValue* size_in_bytes = AddInstruction(new(zone) HConstant(size)); 1623 HValue* size_in_bytes = Add<HConstant>(size);
1628 HInstruction* object = 1624 HInstruction* object = Add<HAllocate>(context,
1629 AddInstruction(new(zone) HAllocate(context, 1625 size_in_bytes,
1630 size_in_bytes, 1626 HType::JSObject(),
1631 HType::JSObject(), 1627 allocate_flags);
1632 allocate_flags));
1633 1628
1634 // Copy the JS array part. 1629 // Copy the JS array part.
1635 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { 1630 for (int i = 0; i < JSArray::kSize; i += kPointerSize) {
1636 if ((i != JSArray::kElementsOffset) || (length == 0)) { 1631 if ((i != JSArray::kElementsOffset) || (length == 0)) {
1637 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i); 1632 HObjectAccess access = HObjectAccess::ForJSArrayOffset(i);
1638 AddStore(object, access, AddLoad(boilerplate, access)); 1633 AddStore(object, access, AddLoad(boilerplate, access));
1639 } 1634 }
1640 } 1635 }
1641 1636
1642 // Create an allocation site info if requested. 1637 // Create an allocation site info if requested.
1643 if (mode == TRACK_ALLOCATION_SITE) { 1638 if (mode == TRACK_ALLOCATION_SITE) {
1644 BuildCreateAllocationSiteInfo(object, JSArray::kSize, boilerplate); 1639 BuildCreateAllocationSiteInfo(object, JSArray::kSize, allocation_site);
1645 } 1640 }
1646 1641
1647 if (length > 0) { 1642 if (length > 0) {
1648 // Get hold of the elements array of the boilerplate and setup the 1643 // Get hold of the elements array of the boilerplate and setup the
1649 // elements pointer in the resulting object. 1644 // elements pointer in the resulting object.
1650 HValue* boilerplate_elements = AddLoadElements(boilerplate); 1645 HValue* boilerplate_elements = AddLoadElements(boilerplate);
1651 HValue* object_elements = 1646 HValue* object_elements = Add<HInnerAllocatedObject>(object, elems_offset);
1652 AddInstruction(new(zone) HInnerAllocatedObject(object, elems_offset));
1653 AddStore(object, HObjectAccess::ForElementsPointer(), object_elements); 1647 AddStore(object, HObjectAccess::ForElementsPointer(), object_elements);
1654 1648
1655 // Copy the elements array header. 1649 // Copy the elements array header.
1656 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) { 1650 for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) {
1657 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i); 1651 HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i);
1658 AddStore(object_elements, access, AddLoad(boilerplate_elements, access)); 1652 AddStore(object_elements, access, AddLoad(boilerplate_elements, access));
1659 } 1653 }
1660 1654
1661 // Copy the elements array contents. 1655 // Copy the elements array contents.
1662 // TODO(mstarzinger): Teach HGraphBuilder::BuildCopyElements to unfold 1656 // TODO(mstarzinger): Teach HGraphBuilder::BuildCopyElements to unfold
1663 // copying loops with constant length up to a given boundary and use this 1657 // copying loops with constant length up to a given boundary and use this
1664 // helper here instead. 1658 // helper here instead.
1665 for (int i = 0; i < length; i++) { 1659 for (int i = 0; i < length; i++) {
1666 HValue* key_constant = AddInstruction(new(zone) HConstant(i)); 1660 HValue* key_constant = Add<HConstant>(i);
1667 HInstruction* value = 1661 HInstruction* value = Add<HLoadKeyed>(boilerplate_elements, key_constant,
1668 AddInstruction(new(zone) HLoadKeyed(boilerplate_elements, 1662 static_cast<HValue*>(NULL), kind);
1669 key_constant, 1663 Add<HStoreKeyed>(object_elements, key_constant, value, kind);
1670 NULL,
1671 kind));
1672 AddInstruction(new(zone) HStoreKeyed(object_elements,
1673 key_constant,
1674 value,
1675 kind));
1676 } 1664 }
1677 } 1665 }
1678 1666
1679 return object; 1667 return object;
1680 } 1668 }
1681 1669
1682 1670
1671 HInstruction* HGraphBuilder::BuildUnaryMathOp(
1672 HValue* input, Handle<Type> type, Token::Value operation) {
1673 // We only handle the numeric cases here
1674 type = handle(
1675 Type::Intersect(type, handle(Type::Number(), isolate())), isolate());
1676
1677 switch (operation) {
1678 default:
1679 UNREACHABLE();
1680 case Token::SUB: {
1681 HInstruction* instr =
1682 HMul::New(zone(), environment()->LookupContext(),
1683 input, graph()->GetConstantMinus1());
1684 Representation rep = Representation::FromType(type);
1685 if (type->Is(Type::None())) {
1686 AddSoftDeoptimize();
1687 }
1688 if (instr->IsBinaryOperation()) {
1689 HBinaryOperation* binop = HBinaryOperation::cast(instr);
1690 binop->set_observed_input_representation(1, rep);
1691 binop->set_observed_input_representation(2, rep);
1692 }
1693 return instr;
1694 }
1695 case Token::BIT_NOT:
1696 if (type->Is(Type::None())) {
1697 AddSoftDeoptimize();
1698 }
1699 return new(zone()) HBitNot(input);
1700 }
1701 }
1702
1703
1683 void HGraphBuilder::BuildCompareNil( 1704 void HGraphBuilder::BuildCompareNil(
1684 HValue* value, 1705 HValue* value,
1685 Handle<Type> type, 1706 Handle<Type> type,
1686 int position, 1707 int position,
1687 HIfContinuation* continuation) { 1708 HIfContinuation* continuation) {
1688 IfBuilder if_nil(this, position); 1709 IfBuilder if_nil(this, position);
1689 bool needs_or = false; 1710 bool needs_or = false;
1690 if (type->Maybe(Type::Null())) { 1711 if (type->Maybe(Type::Null())) {
1691 if (needs_or) if_nil.Or(); 1712 if (needs_or) if_nil.Or();
1692 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull()); 1713 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull());
(...skipping 22 matching lines...) Expand all
1715 if_nil.Deopt(); 1736 if_nil.Deopt();
1716 } 1737 }
1717 } 1738 }
1718 1739
1719 if_nil.CaptureContinuation(continuation); 1740 if_nil.CaptureContinuation(continuation);
1720 } 1741 }
1721 1742
1722 1743
1723 HValue* HGraphBuilder::BuildCreateAllocationSiteInfo(HValue* previous_object, 1744 HValue* HGraphBuilder::BuildCreateAllocationSiteInfo(HValue* previous_object,
1724 int previous_object_size, 1745 int previous_object_size,
1725 HValue* payload) { 1746 HValue* alloc_site) {
1726 HInnerAllocatedObject* alloc_site = new(zone()) 1747 ASSERT(alloc_site != NULL);
1727 HInnerAllocatedObject(previous_object, previous_object_size); 1748 HInnerAllocatedObject* alloc_site_info = Add<HInnerAllocatedObject>(
1728 AddInstruction(alloc_site); 1749 previous_object, previous_object_size);
1729 Handle<Map> alloc_site_map(isolate()->heap()->allocation_site_info_map()); 1750 Handle<Map> alloc_site_info_map(
1730 AddStoreMapConstant(alloc_site, alloc_site_map); 1751 isolate()->heap()->allocation_site_info_map());
1731 HObjectAccess access = HObjectAccess::ForAllocationSitePayload(); 1752 AddStoreMapConstant(alloc_site_info, alloc_site_info_map);
1732 AddStore(alloc_site, access, payload); 1753 HObjectAccess access = HObjectAccess::ForAllocationSiteInfoSite();
1733 return alloc_site; 1754 AddStore(alloc_site_info, access, alloc_site);
1755 return alloc_site_info;
1734 } 1756 }
1735 1757
1736 1758
1737 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* context) { 1759 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* context) {
1738 // Get the global context, then the native context 1760 // Get the global context, then the native context
1739 HInstruction* global_object = AddInstruction(new(zone()) 1761 HInstruction* global_object = Add<HGlobalObject>(context);
1740 HGlobalObject(context));
1741 HObjectAccess access = HObjectAccess::ForJSObjectOffset( 1762 HObjectAccess access = HObjectAccess::ForJSObjectOffset(
1742 GlobalObject::kNativeContextOffset); 1763 GlobalObject::kNativeContextOffset);
1743 return AddLoad(global_object, access); 1764 return AddLoad(global_object, access);
1744 } 1765 }
1745 1766
1746 1767
1747 HInstruction* HGraphBuilder::BuildGetArrayFunction(HValue* context) { 1768 HInstruction* HGraphBuilder::BuildGetArrayFunction(HValue* context) {
1748 HInstruction* native_context = BuildGetNativeContext(context); 1769 HInstruction* native_context = BuildGetNativeContext(context);
1749 HInstruction* index = AddInstruction(new(zone()) 1770 HInstruction* index =
1750 HConstant(Context::ARRAY_FUNCTION_INDEX)); 1771 Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX));
1751 1772 return Add<HLoadKeyed>(
1752 return AddInstruction(new (zone()) 1773 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
1753 HLoadKeyed(native_context, index, NULL, FAST_ELEMENTS));
1754 } 1774 }
1755 1775
1756 1776
1757 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, 1777 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
1758 ElementsKind kind, 1778 ElementsKind kind,
1759 HValue* allocation_site_payload, 1779 HValue* allocation_site_payload,
1760 bool disable_allocation_sites) : 1780 HValue* constructor_function,
1781 AllocationSiteOverrideMode override_mode) :
1761 builder_(builder), 1782 builder_(builder),
1762 kind_(kind), 1783 kind_(kind),
1763 allocation_site_payload_(allocation_site_payload), 1784 allocation_site_payload_(allocation_site_payload),
1764 constructor_function_(NULL) { 1785 constructor_function_(constructor_function) {
1765 mode_ = disable_allocation_sites 1786 mode_ = override_mode == DISABLE_ALLOCATION_SITES
1766 ? DONT_TRACK_ALLOCATION_SITE 1787 ? DONT_TRACK_ALLOCATION_SITE
1767 : AllocationSiteInfo::GetMode(kind); 1788 : AllocationSite::GetMode(kind);
1768 } 1789 }
1769 1790
1770 1791
1771 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, 1792 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
1772 ElementsKind kind, 1793 ElementsKind kind,
1773 HValue* constructor_function) : 1794 HValue* constructor_function) :
1774 builder_(builder), 1795 builder_(builder),
1775 kind_(kind), 1796 kind_(kind),
1776 mode_(DONT_TRACK_ALLOCATION_SITE), 1797 mode_(DONT_TRACK_ALLOCATION_SITE),
1777 allocation_site_payload_(NULL), 1798 allocation_site_payload_(NULL),
1778 constructor_function_(constructor_function) { 1799 constructor_function_(constructor_function) {
1779 } 1800 }
1780 1801
1781 1802
1782 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) { 1803 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) {
1804 if (kind_ == GetInitialFastElementsKind()) {
1805 // No need for a context lookup if the kind_ matches the initial
1806 // map, because we can just load the map in that case.
1807 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
1808 HInstruction* load =
1809 builder()->BuildLoadNamedField(constructor_function_,
1810 access,
1811 Representation::Tagged());
1812 return builder()->AddInstruction(load);
1813 }
1814
1783 HInstruction* native_context = builder()->BuildGetNativeContext(context); 1815 HInstruction* native_context = builder()->BuildGetNativeContext(context);
1816 HInstruction* index = builder()->Add<HConstant>(
1817 static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX));
1784 1818
1785 HInstruction* index = builder()->AddInstruction(new(zone()) 1819 HInstruction* map_array = builder()->Add<HLoadKeyed>(
1786 HConstant(Context::JS_ARRAY_MAPS_INDEX)); 1820 native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
1787 1821
1788 HInstruction* map_array = builder()->AddInstruction(new(zone()) 1822 HInstruction* kind_index = builder()->Add<HConstant>(kind_);
1789 HLoadKeyed(native_context, index, NULL, FAST_ELEMENTS));
1790 1823
1791 HInstruction* kind_index = builder()->AddInstruction(new(zone()) 1824 return builder()->Add<HLoadKeyed>(
1792 HConstant(kind_)); 1825 map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
1793
1794 return builder()->AddInstruction(new(zone())
1795 HLoadKeyed(map_array, kind_index, NULL, FAST_ELEMENTS));
1796 } 1826 }
1797 1827
1798 1828
1799 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() { 1829 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() {
1800 // Find the map near the constructor function 1830 // Find the map near the constructor function
1801 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap(); 1831 HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
1802 return AddInstruction( 1832 return builder()->AddInstruction(
1803 builder()->BuildLoadNamedField(constructor_function_, 1833 builder()->BuildLoadNamedField(constructor_function_,
1804 access, 1834 access,
1805 Representation::Tagged())); 1835 Representation::Tagged()));
1806 } 1836 }
1807 1837
1808 1838
1809 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize( 1839 HValue* HGraphBuilder::JSArrayBuilder::EstablishAllocationSize(
1810 HValue* length_node) { 1840 HValue* length_node) {
1811 HValue* context = builder()->environment()->LookupContext(); 1841 HValue* context = builder()->environment()->LookupContext();
1812 ASSERT(length_node != NULL); 1842 ASSERT(length_node != NULL);
1813 1843
1814 int base_size = JSArray::kSize; 1844 int base_size = JSArray::kSize;
1815 if (mode_ == TRACK_ALLOCATION_SITE) { 1845 if (mode_ == TRACK_ALLOCATION_SITE) {
1816 base_size += AllocationSiteInfo::kSize; 1846 base_size += AllocationSiteInfo::kSize;
1817 } 1847 }
1818 1848
1819 if (IsFastDoubleElementsKind(kind_)) { 1849 if (IsFastDoubleElementsKind(kind_)) {
1820 base_size += FixedDoubleArray::kHeaderSize; 1850 base_size += FixedDoubleArray::kHeaderSize;
1821 } else { 1851 } else {
1822 base_size += FixedArray::kHeaderSize; 1852 base_size += FixedArray::kHeaderSize;
1823 } 1853 }
1824 1854
1825 HInstruction* elements_size_value = new(zone()) HConstant(elements_size()); 1855 HInstruction* elements_size_value =
1826 AddInstruction(elements_size_value); 1856 builder()->Add<HConstant>(elements_size());
1827 HInstruction* mul = HMul::New(zone(), context, length_node, 1857 HInstruction* mul = HMul::New(zone(), context, length_node,
1828 elements_size_value); 1858 elements_size_value);
1829 mul->ClearFlag(HValue::kCanOverflow); 1859 mul->ClearFlag(HValue::kCanOverflow);
1830 AddInstruction(mul); 1860 builder()->AddInstruction(mul);
1831 1861
1832 HInstruction* base = new(zone()) HConstant(base_size); 1862 HInstruction* base = builder()->Add<HConstant>(base_size);
1833 AddInstruction(base);
1834 HInstruction* total_size = HAdd::New(zone(), context, base, mul); 1863 HInstruction* total_size = HAdd::New(zone(), context, base, mul);
1835 total_size->ClearFlag(HValue::kCanOverflow); 1864 total_size->ClearFlag(HValue::kCanOverflow);
1836 AddInstruction(total_size); 1865 builder()->AddInstruction(total_size);
1837 return total_size; 1866 return total_size;
1838 } 1867 }
1839 1868
1840 1869
1841 HValue* HGraphBuilder::JSArrayBuilder::EstablishEmptyArrayAllocationSize() { 1870 HValue* HGraphBuilder::JSArrayBuilder::EstablishEmptyArrayAllocationSize() {
1842 int base_size = JSArray::kSize; 1871 int base_size = JSArray::kSize;
1843 if (mode_ == TRACK_ALLOCATION_SITE) { 1872 if (mode_ == TRACK_ALLOCATION_SITE) {
1844 base_size += AllocationSiteInfo::kSize; 1873 base_size += AllocationSiteInfo::kSize;
1845 } 1874 }
1846 1875
1847 base_size += IsFastDoubleElementsKind(kind_) 1876 base_size += IsFastDoubleElementsKind(kind_)
1848 ? FixedDoubleArray::SizeFor(initial_capacity()) 1877 ? FixedDoubleArray::SizeFor(initial_capacity())
1849 : FixedArray::SizeFor(initial_capacity()); 1878 : FixedArray::SizeFor(initial_capacity());
1850 1879
1851 HConstant* array_size = new(zone()) HConstant(base_size); 1880 return builder()->Add<HConstant>(base_size);
1852 AddInstruction(array_size);
1853 return array_size;
1854 } 1881 }
1855 1882
1856 1883
1857 HValue* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() { 1884 HValue* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() {
1858 HValue* size_in_bytes = EstablishEmptyArrayAllocationSize(); 1885 HValue* size_in_bytes = EstablishEmptyArrayAllocationSize();
1859 HConstant* capacity = new(zone()) HConstant(initial_capacity()); 1886 HConstant* capacity = builder()->Add<HConstant>(initial_capacity());
1860 AddInstruction(capacity);
1861 return AllocateArray(size_in_bytes, 1887 return AllocateArray(size_in_bytes,
1862 capacity, 1888 capacity,
1863 builder()->graph()->GetConstant0(), 1889 builder()->graph()->GetConstant0(),
1864 true); 1890 true);
1865 } 1891 }
1866 1892
1867 1893
1868 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* capacity, 1894 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* capacity,
1869 HValue* length_field, 1895 HValue* length_field,
1870 bool fill_with_hole) { 1896 bool fill_with_hole) {
1871 HValue* size_in_bytes = EstablishAllocationSize(capacity); 1897 HValue* size_in_bytes = EstablishAllocationSize(capacity);
1872 return AllocateArray(size_in_bytes, capacity, length_field, fill_with_hole); 1898 return AllocateArray(size_in_bytes, capacity, length_field, fill_with_hole);
1873 } 1899 }
1874 1900
1875 1901
1876 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes, 1902 HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes,
1877 HValue* capacity, 1903 HValue* capacity,
1878 HValue* length_field, 1904 HValue* length_field,
1879 bool fill_with_hole) { 1905 bool fill_with_hole) {
1880 HValue* context = builder()->environment()->LookupContext(); 1906 HValue* context = builder()->environment()->LookupContext();
1881 1907
1882 // Allocate (dealing with failure appropriately) 1908 // Allocate (dealing with failure appropriately)
1883 HAllocate::Flags flags = HAllocate::DefaultFlags(kind_); 1909 HAllocate::Flags flags = HAllocate::DefaultFlags(kind_);
1884 HAllocate* new_object = new(zone()) HAllocate(context, size_in_bytes, 1910 HAllocate* new_object = builder()->Add<HAllocate>(context, size_in_bytes,
1885 HType::JSArray(), flags); 1911 HType::JSArray(), flags);
1886 AddInstruction(new_object);
1887 1912
1888 // Fill in the fields: map, properties, length 1913 // Fill in the fields: map, properties, length
1889 HValue* map; 1914 HValue* map;
1890 if (constructor_function_ != NULL) { 1915 if (allocation_site_payload_ == NULL) {
1891 map = EmitInternalMapCode(); 1916 map = EmitInternalMapCode();
1892 } else { 1917 } else {
1893 map = EmitMapCode(context); 1918 map = EmitMapCode(context);
1894 } 1919 }
1895 elements_location_ = builder()->BuildJSArrayHeader(new_object, 1920 elements_location_ = builder()->BuildJSArrayHeader(new_object,
1896 map, 1921 map,
1897 mode_, 1922 mode_,
1898 allocation_site_payload_, 1923 allocation_site_payload_,
1899 length_field); 1924 length_field);
1900 1925
1901 // Initialize the elements 1926 // Initialize the elements
1902 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity); 1927 builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity);
1903 1928
1904 if (fill_with_hole) { 1929 if (fill_with_hole) {
1905 builder()->BuildFillElementsWithHole(context, elements_location_, kind_, 1930 builder()->BuildFillElementsWithHole(context, elements_location_, kind_,
1906 graph()->GetConstant0(), capacity); 1931 graph()->GetConstant0(), capacity);
1907 } 1932 }
1908 1933
1909 return new_object; 1934 return new_object;
1910 } 1935 }
1911 1936
1912 1937
1913 HStoreNamedField* HGraphBuilder::AddStore(HValue *object, 1938 HStoreNamedField* HGraphBuilder::AddStore(HValue *object,
1914 HObjectAccess access, 1939 HObjectAccess access,
1915 HValue *val, 1940 HValue *val,
1916 Representation representation) { 1941 Representation representation) {
1917 HStoreNamedField *instr = new(zone()) 1942 return Add<HStoreNamedField>(object, access, val, representation);
1918 HStoreNamedField(object, access, val, representation);
1919 AddInstruction(instr);
1920 return instr;
1921 } 1943 }
1922 1944
1923 1945
1924 HLoadNamedField* HGraphBuilder::AddLoad(HValue *object, 1946 HLoadNamedField* HGraphBuilder::AddLoad(HValue *object,
1925 HObjectAccess access, 1947 HObjectAccess access,
1926 HValue *typecheck, 1948 HValue *typecheck,
1927 Representation representation) { 1949 Representation representation) {
1928 HLoadNamedField *instr = 1950 return Add<HLoadNamedField>(object, access, typecheck, representation);
1929 new(zone()) HLoadNamedField(object, access, typecheck, representation);
1930 AddInstruction(instr);
1931 return instr;
1932 } 1951 }
1933 1952
1934 1953
1935 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object, 1954 HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object,
1936 Handle<Map> map) { 1955 Handle<Map> map) {
1937 HValue* constant = AddInstruction(new(zone()) HConstant(map)); 1956 return Add<HStoreNamedField>(object, HObjectAccess::ForMap(),
1938 HStoreNamedField *instr = 1957 Add<HConstant>(map));
1939 new(zone()) HStoreNamedField(object, HObjectAccess::ForMap(), constant);
1940 AddInstruction(instr);
1941 return instr;
1942 } 1958 }
1943 1959
1944 1960
1961 HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin,
1962 HContext* context) {
1963 HGlobalObject* global_object = Add<HGlobalObject>(context);
1964 HObjectAccess access = HObjectAccess::ForJSObjectOffset(
1965 GlobalObject::kBuiltinsOffset);
1966 HValue* builtins = AddLoad(global_object, access);
1967 HObjectAccess function_access = HObjectAccess::ForJSObjectOffset(
1968 JSBuiltinsObject::OffsetOfFunctionWithId(builtin));
1969 return AddLoad(builtins, function_access);
1970 }
1971
1972
1945 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info) 1973 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info)
1946 : HGraphBuilder(info), 1974 : HGraphBuilder(info),
1947 function_state_(NULL), 1975 function_state_(NULL),
1948 initial_function_state_(this, info, NORMAL_RETURN), 1976 initial_function_state_(this, info, NORMAL_RETURN),
1949 ast_context_(NULL), 1977 ast_context_(NULL),
1950 break_scope_(NULL), 1978 break_scope_(NULL),
1951 inlined_count_(0), 1979 inlined_count_(0),
1952 globals_(10, info->zone()), 1980 globals_(10, info->zone()),
1953 inline_bailout_(false) { 1981 inline_bailout_(false),
1982 osr_(new(info->zone()) HOsrBuilder(this)) {
1954 // This is not initialized in the initializer list because the 1983 // This is not initialized in the initializer list because the
1955 // constructor for the initial state relies on function_state_ == NULL 1984 // constructor for the initial state relies on function_state_ == NULL
1956 // to know it's the initial state. 1985 // to know it's the initial state.
1957 function_state_= &initial_function_state_; 1986 function_state_= &initial_function_state_;
1958 InitializeAstVisitor(); 1987 InitializeAstVisitor();
1959 } 1988 }
1960 1989
1961 1990
1962 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first, 1991 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first,
1963 HBasicBlock* second, 1992 HBasicBlock* second,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
2011 2040
2012 2041
2013 HGraph::HGraph(CompilationInfo* info) 2042 HGraph::HGraph(CompilationInfo* info)
2014 : isolate_(info->isolate()), 2043 : isolate_(info->isolate()),
2015 next_block_id_(0), 2044 next_block_id_(0),
2016 entry_block_(NULL), 2045 entry_block_(NULL),
2017 blocks_(8, info->zone()), 2046 blocks_(8, info->zone()),
2018 values_(16, info->zone()), 2047 values_(16, info->zone()),
2019 phi_list_(NULL), 2048 phi_list_(NULL),
2020 uint32_instructions_(NULL), 2049 uint32_instructions_(NULL),
2050 osr_(NULL),
2021 info_(info), 2051 info_(info),
2022 zone_(info->zone()), 2052 zone_(info->zone()),
2023 is_recursive_(false), 2053 is_recursive_(false),
2024 use_optimistic_licm_(false), 2054 use_optimistic_licm_(false),
2025 has_soft_deoptimize_(false), 2055 has_soft_deoptimize_(false),
2026 depends_on_empty_array_proto_elements_(false), 2056 depends_on_empty_array_proto_elements_(false),
2027 type_change_checksum_(0), 2057 type_change_checksum_(0),
2028 maximum_environment_size_(0) { 2058 maximum_environment_size_(0) {
2029 if (info->IsStub()) { 2059 if (info->IsStub()) {
2030 HydrogenCodeStub* stub = info->code_stub(); 2060 HydrogenCodeStub* stub = info->code_stub();
(...skipping 15 matching lines...) Expand all
2046 HBasicBlock* result = new(zone()) HBasicBlock(this); 2076 HBasicBlock* result = new(zone()) HBasicBlock(this);
2047 blocks_.Add(result, zone()); 2077 blocks_.Add(result, zone());
2048 return result; 2078 return result;
2049 } 2079 }
2050 2080
2051 2081
2052 void HGraph::FinalizeUniqueValueIds() { 2082 void HGraph::FinalizeUniqueValueIds() {
2053 DisallowHeapAllocation no_gc; 2083 DisallowHeapAllocation no_gc;
2054 ASSERT(!isolate()->optimizing_compiler_thread()->IsOptimizerThread()); 2084 ASSERT(!isolate()->optimizing_compiler_thread()->IsOptimizerThread());
2055 for (int i = 0; i < blocks()->length(); ++i) { 2085 for (int i = 0; i < blocks()->length(); ++i) {
2056 for (HInstruction* instr = blocks()->at(i)->first(); 2086 for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
2057 instr != NULL; 2087 it.Current()->FinalizeUniqueValueId();
2058 instr = instr->next()) {
2059 instr->FinalizeUniqueValueId();
2060 } 2088 }
2061 } 2089 }
2062 } 2090 }
2063 2091
2064 2092
2065 void HGraph::Canonicalize() { 2093 void HGraph::Canonicalize() {
2066 HPhase phase("H_Canonicalize", this); 2094 HPhase phase("H_Canonicalize", this);
2067 // Before removing no-op instructions, save their semantic value. 2095 // Before removing no-op instructions, save their semantic value.
2068 // We must be careful not to set the flag unnecessarily, because GVN 2096 // We must be careful not to set the flag unnecessarily, because GVN
2069 // cannot identify two instructions when their flag value differs. 2097 // cannot identify two instructions when their flag value differs.
2070 for (int i = 0; i < blocks()->length(); ++i) { 2098 for (int i = 0; i < blocks()->length(); ++i) {
2071 HInstruction* instr = blocks()->at(i)->first(); 2099 for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
2072 while (instr != NULL) { 2100 HInstruction* instr = it.Current();
2073 if (instr->IsArithmeticBinaryOperation() && 2101 if (instr->IsArithmeticBinaryOperation() &&
2074 instr->representation().IsInteger32() && 2102 instr->representation().IsInteger32() &&
2075 instr->HasAtLeastOneUseWithFlagAndNoneWithout( 2103 instr->HasAtLeastOneUseWithFlagAndNoneWithout(
2076 HInstruction::kTruncatingToInt32)) { 2104 HInstruction::kTruncatingToInt32)) {
2077 instr->SetFlag(HInstruction::kAllUsesTruncatingToInt32); 2105 instr->SetFlag(HInstruction::kAllUsesTruncatingToInt32);
2078 } 2106 }
2079 instr = instr->next();
2080 } 2107 }
2081 } 2108 }
2082 // Perform actual Canonicalization pass. 2109 // Perform actual Canonicalization pass.
2083 for (int i = 0; i < blocks()->length(); ++i) { 2110 for (int i = 0; i < blocks()->length(); ++i) {
2084 HInstruction* instr = blocks()->at(i)->first(); 2111 for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
2085 while (instr != NULL) { 2112 HInstruction* instr = it.Current();
2086 HValue* value = instr->Canonicalize(); 2113 HValue* value = instr->Canonicalize();
2087 if (value != instr) instr->DeleteAndReplaceWith(value); 2114 if (value != instr) instr->DeleteAndReplaceWith(value);
2088 instr = instr->next();
2089 } 2115 }
2090 } 2116 }
2091 } 2117 }
2092 2118
2119
2093 // Block ordering was implemented with two mutually recursive methods, 2120 // Block ordering was implemented with two mutually recursive methods,
2094 // HGraph::Postorder and HGraph::PostorderLoopBlocks. 2121 // HGraph::Postorder and HGraph::PostorderLoopBlocks.
2095 // The recursion could lead to stack overflow so the algorithm has been 2122 // The recursion could lead to stack overflow so the algorithm has been
2096 // implemented iteratively. 2123 // implemented iteratively.
2097 // At a high level the algorithm looks like this: 2124 // At a high level the algorithm looks like this:
2098 // 2125 //
2099 // Postorder(block, loop_header) : { 2126 // Postorder(block, loop_header) : {
2100 // if (block has already been visited or is of another loop) return; 2127 // if (block has already been visited or is of another loop) return;
2101 // mark block as visited; 2128 // mark block as visited;
2102 // if (block is a loop header) { 2129 // if (block is a loop header) {
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
2453 const ZoneList<HBasicBlock*>* predecessors = block->predecessors(); 2480 const ZoneList<HBasicBlock*>* predecessors = block->predecessors();
2454 int predecessors_length = predecessors->length(); 2481 int predecessors_length = predecessors->length();
2455 bool all_predecessors_deoptimizing = (predecessors_length > 0); 2482 bool all_predecessors_deoptimizing = (predecessors_length > 0);
2456 for (int j = 0; j < predecessors_length; ++j) { 2483 for (int j = 0; j < predecessors_length; ++j) {
2457 if (!predecessors->at(j)->IsDeoptimizing()) { 2484 if (!predecessors->at(j)->IsDeoptimizing()) {
2458 all_predecessors_deoptimizing = false; 2485 all_predecessors_deoptimizing = false;
2459 break; 2486 break;
2460 } 2487 }
2461 } 2488 }
2462 if (all_predecessors_deoptimizing) nullify = true; 2489 if (all_predecessors_deoptimizing) nullify = true;
2463 for (HInstruction* instr = block->first(); instr != NULL; 2490 for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
2464 instr = instr->next()) { 2491 HInstruction* instr = it.Current();
2465 // Leave the basic structure of the graph intact. 2492 // Leave the basic structure of the graph intact.
2466 if (instr->IsBlockEntry()) continue; 2493 if (instr->IsBlockEntry()) continue;
2467 if (instr->IsControlInstruction()) continue; 2494 if (instr->IsControlInstruction()) continue;
2468 if (instr->IsSimulate()) continue; 2495 if (instr->IsSimulate()) continue;
2469 if (instr->IsEnterInlined()) continue; 2496 if (instr->IsEnterInlined()) continue;
2470 if (instr->IsLeaveInlined()) continue; 2497 if (instr->IsLeaveInlined()) continue;
2471 if (nullify) { 2498 if (nullify) {
2472 HInstruction* last_dummy = NULL; 2499 HInstruction* last_dummy = NULL;
2473 for (int j = 0; j < instr->OperandCount(); ++j) { 2500 for (int j = 0; j < instr->OperandCount(); ++j) {
2474 HValue* operand = instr->OperandAt(j); 2501 HValue* operand = instr->OperandAt(j);
(...skipping 23 matching lines...) Expand all
2498 } 2525 }
2499 if (instr->IsSoftDeoptimize()) { 2526 if (instr->IsSoftDeoptimize()) {
2500 ASSERT(block->IsDeoptimizing()); 2527 ASSERT(block->IsDeoptimizing());
2501 nullify = true; 2528 nullify = true;
2502 } 2529 }
2503 } 2530 }
2504 } 2531 }
2505 } 2532 }
2506 2533
2507 2534
2508 // Replace all phis consisting of a single non-loop operand plus any number of
2509 // loop operands by that single non-loop operand.
2510 void HGraph::EliminateRedundantPhis() {
2511 HPhase phase("H_Redundant phi elimination", this);
2512
2513 // We do a simple fixed point iteration without any work list, because
2514 // machine-generated JavaScript can lead to a very dense Hydrogen graph with
2515 // an enormous work list and will consequently result in OOM. Experiments
2516 // showed that this simple algorithm is good enough, and even e.g. tracking
2517 // the set or range of blocks to consider is not a real improvement.
2518 bool need_another_iteration;
2519 ZoneList<HPhi*> redundant_phis(blocks_.length(), zone());
2520 do {
2521 need_another_iteration = false;
2522 for (int i = 0; i < blocks_.length(); ++i) {
2523 HBasicBlock* block = blocks_[i];
2524 for (int j = 0; j < block->phis()->length(); j++) {
2525 HPhi* phi = block->phis()->at(j);
2526 HValue* replacement = phi->GetRedundantReplacement();
2527 if (replacement != NULL) {
2528 // Remember phi to avoid concurrent modification of the block's phis.
2529 redundant_phis.Add(phi, zone());
2530 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
2531 HValue* value = it.value();
2532 value->SetOperandAt(it.index(), replacement);
2533 need_another_iteration |= value->IsPhi();
2534 }
2535 }
2536 }
2537 for (int i = 0; i < redundant_phis.length(); i++) {
2538 block->RemovePhi(redundant_phis[i]);
2539 }
2540 redundant_phis.Clear();
2541 }
2542 } while (need_another_iteration);
2543
2544 #if DEBUG
2545 // Make sure that we *really* removed all redundant phis.
2546 for (int i = 0; i < blocks_.length(); ++i) {
2547 for (int j = 0; j < blocks_[i]->phis()->length(); j++) {
2548 ASSERT(blocks_[i]->phis()->at(j)->GetRedundantReplacement() == NULL);
2549 }
2550 }
2551 #endif
2552 }
2553
2554
2555 bool HGraph::CheckArgumentsPhiUses() { 2535 bool HGraph::CheckArgumentsPhiUses() {
2556 int block_count = blocks_.length(); 2536 int block_count = blocks_.length();
2557 for (int i = 0; i < block_count; ++i) { 2537 for (int i = 0; i < block_count; ++i) {
2558 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) { 2538 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
2559 HPhi* phi = blocks_[i]->phis()->at(j); 2539 HPhi* phi = blocks_[i]->phis()->at(j);
2560 // We don't support phi uses of arguments for now. 2540 // We don't support phi uses of arguments for now.
2561 if (phi->CheckFlag(HValue::kIsArguments)) return false; 2541 if (phi->CheckFlag(HValue::kIsArguments)) return false;
2562 } 2542 }
2563 } 2543 }
2564 return true; 2544 return true;
(...skipping 20 matching lines...) Expand all
2585 phi_list_ = new(zone()) ZoneList<HPhi*>(block_count, zone()); 2565 phi_list_ = new(zone()) ZoneList<HPhi*>(block_count, zone());
2586 for (int i = 0; i < block_count; ++i) { 2566 for (int i = 0; i < block_count; ++i) {
2587 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) { 2567 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
2588 HPhi* phi = blocks_[i]->phis()->at(j); 2568 HPhi* phi = blocks_[i]->phis()->at(j);
2589 phi_list_->Add(phi, zone()); 2569 phi_list_->Add(phi, zone());
2590 } 2570 }
2591 } 2571 }
2592 } 2572 }
2593 2573
2594 2574
2595 void HGraph::InferTypes(ZoneList<HValue*>* worklist) {
2596 BitVector in_worklist(GetMaximumValueID(), zone());
2597 for (int i = 0; i < worklist->length(); ++i) {
2598 ASSERT(!in_worklist.Contains(worklist->at(i)->id()));
2599 in_worklist.Add(worklist->at(i)->id());
2600 }
2601
2602 while (!worklist->is_empty()) {
2603 HValue* current = worklist->RemoveLast();
2604 in_worklist.Remove(current->id());
2605 if (current->UpdateInferredType()) {
2606 for (HUseIterator it(current->uses()); !it.Done(); it.Advance()) {
2607 HValue* use = it.value();
2608 if (!in_worklist.Contains(use->id())) {
2609 in_worklist.Add(use->id());
2610 worklist->Add(use, zone());
2611 }
2612 }
2613 }
2614 }
2615 }
2616
2617
2618 class HRangeAnalysis BASE_EMBEDDED {
2619 public:
2620 explicit HRangeAnalysis(HGraph* graph) :
2621 graph_(graph), zone_(graph->zone()), changed_ranges_(16, zone_) { }
2622
2623 void Analyze();
2624
2625 private:
2626 void TraceRange(const char* msg, ...);
2627 void Analyze(HBasicBlock* block);
2628 void InferControlFlowRange(HCompareIDAndBranch* test, HBasicBlock* dest);
2629 void UpdateControlFlowRange(Token::Value op, HValue* value, HValue* other);
2630 void InferRange(HValue* value);
2631 void RollBackTo(int index);
2632 void AddRange(HValue* value, Range* range);
2633
2634 HGraph* graph_;
2635 Zone* zone_;
2636 ZoneList<HValue*> changed_ranges_;
2637 };
2638
2639
2640 void HRangeAnalysis::TraceRange(const char* msg, ...) {
2641 if (FLAG_trace_range) {
2642 va_list arguments;
2643 va_start(arguments, msg);
2644 OS::VPrint(msg, arguments);
2645 va_end(arguments);
2646 }
2647 }
2648
2649
2650 void HRangeAnalysis::Analyze() {
2651 HPhase phase("H_Range analysis", graph_);
2652 Analyze(graph_->entry_block());
2653 }
2654
2655
2656 void HRangeAnalysis::Analyze(HBasicBlock* block) {
2657 TraceRange("Analyzing block B%d\n", block->block_id());
2658
2659 int last_changed_range = changed_ranges_.length() - 1;
2660
2661 // Infer range based on control flow.
2662 if (block->predecessors()->length() == 1) {
2663 HBasicBlock* pred = block->predecessors()->first();
2664 if (pred->end()->IsCompareIDAndBranch()) {
2665 InferControlFlowRange(HCompareIDAndBranch::cast(pred->end()), block);
2666 }
2667 }
2668
2669 // Process phi instructions.
2670 for (int i = 0; i < block->phis()->length(); ++i) {
2671 HPhi* phi = block->phis()->at(i);
2672 InferRange(phi);
2673 }
2674
2675 // Go through all instructions of the current block.
2676 HInstruction* instr = block->first();
2677 while (instr != block->end()) {
2678 InferRange(instr);
2679 instr = instr->next();
2680 }
2681
2682 // Continue analysis in all dominated blocks.
2683 for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
2684 Analyze(block->dominated_blocks()->at(i));
2685 }
2686
2687 RollBackTo(last_changed_range);
2688 }
2689
2690
2691 void HRangeAnalysis::InferControlFlowRange(HCompareIDAndBranch* test,
2692 HBasicBlock* dest) {
2693 ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest));
2694 if (test->representation().IsSmiOrInteger32()) {
2695 Token::Value op = test->token();
2696 if (test->SecondSuccessor() == dest) {
2697 op = Token::NegateCompareOp(op);
2698 }
2699 Token::Value inverted_op = Token::ReverseCompareOp(op);
2700 UpdateControlFlowRange(op, test->left(), test->right());
2701 UpdateControlFlowRange(inverted_op, test->right(), test->left());
2702 }
2703 }
2704
2705
2706 // We know that value [op] other. Use this information to update the range on
2707 // value.
2708 void HRangeAnalysis::UpdateControlFlowRange(Token::Value op,
2709 HValue* value,
2710 HValue* other) {
2711 Range temp_range;
2712 Range* range = other->range() != NULL ? other->range() : &temp_range;
2713 Range* new_range = NULL;
2714
2715 TraceRange("Control flow range infer %d %s %d\n",
2716 value->id(),
2717 Token::Name(op),
2718 other->id());
2719
2720 if (op == Token::EQ || op == Token::EQ_STRICT) {
2721 // The same range has to apply for value.
2722 new_range = range->Copy(zone_);
2723 } else if (op == Token::LT || op == Token::LTE) {
2724 new_range = range->CopyClearLower(zone_);
2725 if (op == Token::LT) {
2726 new_range->AddConstant(-1);
2727 }
2728 } else if (op == Token::GT || op == Token::GTE) {
2729 new_range = range->CopyClearUpper(zone_);
2730 if (op == Token::GT) {
2731 new_range->AddConstant(1);
2732 }
2733 }
2734
2735 if (new_range != NULL && !new_range->IsMostGeneric()) {
2736 AddRange(value, new_range);
2737 }
2738 }
2739
2740
2741 void HRangeAnalysis::InferRange(HValue* value) {
2742 ASSERT(!value->HasRange());
2743 if (!value->representation().IsNone()) {
2744 value->ComputeInitialRange(zone_);
2745 Range* range = value->range();
2746 TraceRange("Initial inferred range of %d (%s) set to [%d,%d]\n",
2747 value->id(),
2748 value->Mnemonic(),
2749 range->lower(),
2750 range->upper());
2751 }
2752 }
2753
2754
2755 void HRangeAnalysis::RollBackTo(int index) {
2756 for (int i = index + 1; i < changed_ranges_.length(); ++i) {
2757 changed_ranges_[i]->RemoveLastAddedRange();
2758 }
2759 changed_ranges_.Rewind(index + 1);
2760 }
2761
2762
2763 void HRangeAnalysis::AddRange(HValue* value, Range* range) {
2764 Range* original_range = value->range();
2765 value->AddNewRange(range, zone_);
2766 changed_ranges_.Add(value, zone_);
2767 Range* new_range = value->range();
2768 TraceRange("Updated range of %d set to [%d,%d]\n",
2769 value->id(),
2770 new_range->lower(),
2771 new_range->upper());
2772 if (original_range != NULL) {
2773 TraceRange("Original range was [%d,%d]\n",
2774 original_range->lower(),
2775 original_range->upper());
2776 }
2777 TraceRange("New information was [%d,%d]\n",
2778 range->lower(),
2779 range->upper());
2780 }
2781
2782
2783 class HStackCheckEliminator BASE_EMBEDDED {
2784 public:
2785 explicit HStackCheckEliminator(HGraph* graph) : graph_(graph) { }
2786
2787 void Process();
2788
2789 private:
2790 HGraph* graph_;
2791 };
2792
2793
2794 void HStackCheckEliminator::Process() {
2795 HPhase phase("H_Stack check elimination", graph_);
2796 // For each loop block walk the dominator tree from the backwards branch to
2797 // the loop header. If a call instruction is encountered the backwards branch
2798 // is dominated by a call and the stack check in the backwards branch can be
2799 // removed.
2800 for (int i = 0; i < graph_->blocks()->length(); i++) {
2801 HBasicBlock* block = graph_->blocks()->at(i);
2802 if (block->IsLoopHeader()) {
2803 HBasicBlock* back_edge = block->loop_information()->GetLastBackEdge();
2804 HBasicBlock* dominator = back_edge;
2805 while (true) {
2806 HInstruction* instr = dominator->first();
2807 while (instr != NULL) {
2808 if (instr->IsCall()) {
2809 block->loop_information()->stack_check()->Eliminate();
2810 break;
2811 }
2812 instr = instr->next();
2813 }
2814
2815 // Done when the loop header is processed.
2816 if (dominator == block) break;
2817
2818 // Move up the dominator tree.
2819 dominator = dominator->dominator();
2820 }
2821 }
2822 }
2823 }
2824
2825
2826 void HInferRepresentation::AddToWorklist(HValue* current) {
2827 if (current->representation().IsTagged()) return;
2828 if (!current->CheckFlag(HValue::kFlexibleRepresentation)) return;
2829 if (in_worklist_.Contains(current->id())) return;
2830 worklist_.Add(current, zone());
2831 in_worklist_.Add(current->id());
2832 }
2833
2834
2835 void HInferRepresentation::Analyze() {
2836 HPhase phase("H_Infer representations", graph_);
2837
2838 // (1) Initialize bit vectors and count real uses. Each phi gets a
2839 // bit-vector of length <number of phis>.
2840 const ZoneList<HPhi*>* phi_list = graph_->phi_list();
2841 int phi_count = phi_list->length();
2842 ZoneList<BitVector*> connected_phis(phi_count, graph_->zone());
2843 for (int i = 0; i < phi_count; ++i) {
2844 phi_list->at(i)->InitRealUses(i);
2845 BitVector* connected_set = new(zone()) BitVector(phi_count, graph_->zone());
2846 connected_set->Add(i);
2847 connected_phis.Add(connected_set, zone());
2848 }
2849
2850 // (2) Do a fixed point iteration to find the set of connected phis. A
2851 // phi is connected to another phi if its value is used either directly or
2852 // indirectly through a transitive closure of the def-use relation.
2853 bool change = true;
2854 while (change) {
2855 change = false;
2856 // We normally have far more "forward edges" than "backward edges",
2857 // so we terminate faster when we walk backwards.
2858 for (int i = phi_count - 1; i >= 0; --i) {
2859 HPhi* phi = phi_list->at(i);
2860 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
2861 HValue* use = it.value();
2862 if (use->IsPhi()) {
2863 int id = HPhi::cast(use)->phi_id();
2864 if (connected_phis[i]->UnionIsChanged(*connected_phis[id]))
2865 change = true;
2866 }
2867 }
2868 }
2869 }
2870
2871 // Set truncation flags for groups of connected phis. This is a conservative
2872 // approximation; the flag will be properly re-computed after representations
2873 // have been determined.
2874 if (phi_count > 0) {
2875 BitVector* done = new(zone()) BitVector(phi_count, graph_->zone());
2876 for (int i = 0; i < phi_count; ++i) {
2877 if (done->Contains(i)) continue;
2878
2879 // Check if all uses of all connected phis in this group are truncating.
2880 bool all_uses_everywhere_truncating = true;
2881 for (BitVector::Iterator it(connected_phis.at(i));
2882 !it.Done();
2883 it.Advance()) {
2884 int index = it.Current();
2885 all_uses_everywhere_truncating &=
2886 phi_list->at(index)->CheckFlag(HInstruction::kTruncatingToInt32);
2887 done->Add(index);
2888 }
2889 if (all_uses_everywhere_truncating) {
2890 continue; // Great, nothing to do.
2891 }
2892 // Clear truncation flag of this group of connected phis.
2893 for (BitVector::Iterator it(connected_phis.at(i));
2894 !it.Done();
2895 it.Advance()) {
2896 int index = it.Current();
2897 phi_list->at(index)->ClearFlag(HInstruction::kTruncatingToInt32);
2898 }
2899 }
2900 }
2901
2902 // Simplify constant phi inputs where possible.
2903 // This step uses kTruncatingToInt32 flags of phis.
2904 for (int i = 0; i < phi_count; ++i) {
2905 phi_list->at(i)->SimplifyConstantInputs();
2906 }
2907
2908 // Use the phi reachability information from step 2 to
2909 // sum up the non-phi use counts of all connected phis.
2910 for (int i = 0; i < phi_count; ++i) {
2911 HPhi* phi = phi_list->at(i);
2912 for (BitVector::Iterator it(connected_phis.at(i));
2913 !it.Done();
2914 it.Advance()) {
2915 int index = it.Current();
2916 HPhi* it_use = phi_list->at(index);
2917 if (index != i) phi->AddNonPhiUsesFrom(it_use); // Don't count twice.
2918 }
2919 }
2920
2921 // Initialize work list
2922 for (int i = 0; i < graph_->blocks()->length(); ++i) {
2923 HBasicBlock* block = graph_->blocks()->at(i);
2924 const ZoneList<HPhi*>* phis = block->phis();
2925 for (int j = 0; j < phis->length(); ++j) {
2926 AddToWorklist(phis->at(j));
2927 }
2928
2929 HInstruction* current = block->first();
2930 while (current != NULL) {
2931 AddToWorklist(current);
2932 current = current->next();
2933 }
2934 }
2935
2936 // Do a fixed point iteration, trying to improve representations
2937 while (!worklist_.is_empty()) {
2938 HValue* current = worklist_.RemoveLast();
2939 in_worklist_.Remove(current->id());
2940 current->InferRepresentation(this);
2941 }
2942
2943 // Lastly: any instruction that we don't have representation information
2944 // for defaults to Tagged.
2945 for (int i = 0; i < graph_->blocks()->length(); ++i) {
2946 HBasicBlock* block = graph_->blocks()->at(i);
2947 const ZoneList<HPhi*>* phis = block->phis();
2948 for (int j = 0; j < phis->length(); ++j) {
2949 HPhi* phi = phis->at(j);
2950 if (phi->representation().IsNone()) {
2951 phi->ChangeRepresentation(Representation::Tagged());
2952 }
2953 }
2954 for (HInstruction* current = block->first();
2955 current != NULL; current = current->next()) {
2956 if (current->representation().IsNone() &&
2957 current->CheckFlag(HInstruction::kFlexibleRepresentation)) {
2958 if (current->CheckFlag(HInstruction::kCannotBeTagged)) {
2959 current->ChangeRepresentation(Representation::Double());
2960 } else {
2961 current->ChangeRepresentation(Representation::Tagged());
2962 }
2963 }
2964 }
2965 }
2966 }
2967
2968
2969 void HGraph::MergeRemovableSimulates() { 2575 void HGraph::MergeRemovableSimulates() {
2970 HPhase phase("H_Merge removable simulates", this); 2576 HPhase phase("H_Merge removable simulates", this);
2971 ZoneList<HSimulate*> mergelist(2, zone()); 2577 ZoneList<HSimulate*> mergelist(2, zone());
2972 for (int i = 0; i < blocks()->length(); ++i) { 2578 for (int i = 0; i < blocks()->length(); ++i) {
2973 HBasicBlock* block = blocks()->at(i); 2579 HBasicBlock* block = blocks()->at(i);
2974 // Make sure the merge list is empty at the start of a block. 2580 // Make sure the merge list is empty at the start of a block.
2975 ASSERT(mergelist.is_empty()); 2581 ASSERT(mergelist.is_empty());
2976 // Nasty heuristic: Never remove the first simulate in a block. This 2582 // Nasty heuristic: Never remove the first simulate in a block. This
2977 // just so happens to have a beneficial effect on register allocation. 2583 // just so happens to have a beneficial effect on register allocation.
2978 bool first = true; 2584 bool first = true;
2979 for (HInstruction* current = block->first(); 2585 for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
2980 current != NULL; current = current->next()) { 2586 HInstruction* current = it.Current();
2981 if (current->IsLeaveInlined()) { 2587 if (current->IsLeaveInlined()) {
2982 // Never fold simulates from inlined environments into simulates 2588 // Never fold simulates from inlined environments into simulates
2983 // in the outer environment. 2589 // in the outer environment.
2984 // (Before each HEnterInlined, there is a non-foldable HSimulate 2590 // (Before each HEnterInlined, there is a non-foldable HSimulate
2985 // anyway, so we get the barrier in the other direction for free.) 2591 // anyway, so we get the barrier in the other direction for free.)
2986 // Simply remove all accumulated simulates without merging. This 2592 // Simply remove all accumulated simulates without merging. This
2987 // is safe because simulates after instructions with side effects 2593 // is safe because simulates after instructions with side effects
2988 // are never added to the merge list. 2594 // are never added to the merge list.
2989 while (!mergelist.is_empty()) { 2595 while (!mergelist.is_empty()) {
2990 mergelist.RemoveLast()->DeleteAndReplaceWith(NULL); 2596 mergelist.RemoveLast()->DeleteAndReplaceWith(NULL);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
3022 2628
3023 if (!mergelist.is_empty()) { 2629 if (!mergelist.is_empty()) {
3024 // Merge the accumulated simulates at the end of the block. 2630 // Merge the accumulated simulates at the end of the block.
3025 HSimulate* last = mergelist.RemoveLast(); 2631 HSimulate* last = mergelist.RemoveLast();
3026 last->MergeWith(&mergelist); 2632 last->MergeWith(&mergelist);
3027 } 2633 }
3028 } 2634 }
3029 } 2635 }
3030 2636
3031 2637
3032 void HGraph::InitializeInferredTypes() {
3033 HPhase phase("H_Inferring types", this);
3034 InitializeInferredTypes(0, this->blocks_.length() - 1);
3035 }
3036
3037
3038 void HGraph::InitializeInferredTypes(int from_inclusive, int to_inclusive) {
3039 for (int i = from_inclusive; i <= to_inclusive; ++i) {
3040 HBasicBlock* block = blocks_[i];
3041
3042 const ZoneList<HPhi*>* phis = block->phis();
3043 for (int j = 0; j < phis->length(); j++) {
3044 phis->at(j)->UpdateInferredType();
3045 }
3046
3047 HInstruction* current = block->first();
3048 while (current != NULL) {
3049 current->UpdateInferredType();
3050 current = current->next();
3051 }
3052
3053 if (block->IsLoopHeader()) {
3054 HBasicBlock* last_back_edge =
3055 block->loop_information()->GetLastBackEdge();
3056 InitializeInferredTypes(i + 1, last_back_edge->block_id());
3057 // Skip all blocks already processed by the recursive call.
3058 i = last_back_edge->block_id();
3059 // Update phis of the loop header now after the whole loop body is
3060 // guaranteed to be processed.
3061 ZoneList<HValue*> worklist(block->phis()->length(), zone());
3062 for (int j = 0; j < block->phis()->length(); ++j) {
3063 worklist.Add(block->phis()->at(j), zone());
3064 }
3065 InferTypes(&worklist);
3066 }
3067 }
3068 }
3069
3070
3071 void HGraph::PropagateMinusZeroChecks(HValue* value, BitVector* visited) { 2638 void HGraph::PropagateMinusZeroChecks(HValue* value, BitVector* visited) {
3072 HValue* current = value; 2639 HValue* current = value;
3073 while (current != NULL) { 2640 while (current != NULL) {
3074 if (visited->Contains(current->id())) return; 2641 if (visited->Contains(current->id())) return;
3075 2642
3076 // For phis, we must propagate the check to all of its inputs. 2643 // For phis, we must propagate the check to all of its inputs.
3077 if (current->IsPhi()) { 2644 if (current->IsPhi()) {
3078 visited->Add(current->id()); 2645 visited->Add(current->id());
3079 HPhi* phi = HPhi::cast(current); 2646 HPhi* phi = HPhi::cast(current);
3080 for (int i = 0; i < phi->OperandCount(); ++i) { 2647 for (int i = 0; i < phi->OperandCount(); ++i) {
(...skipping 19 matching lines...) Expand all
3100 visited->Add(minmax->id()); 2667 visited->Add(minmax->id());
3101 PropagateMinusZeroChecks(minmax->left(), visited); 2668 PropagateMinusZeroChecks(minmax->left(), visited);
3102 PropagateMinusZeroChecks(minmax->right(), visited); 2669 PropagateMinusZeroChecks(minmax->right(), visited);
3103 } 2670 }
3104 2671
3105 current = current->EnsureAndPropagateNotMinusZero(visited); 2672 current = current->EnsureAndPropagateNotMinusZero(visited);
3106 } 2673 }
3107 } 2674 }
3108 2675
3109 2676
3110 void HGraph::InsertRepresentationChangeForUse(HValue* value,
3111 HValue* use_value,
3112 int use_index,
3113 Representation to) {
3114 // Insert the representation change right before its use. For phi-uses we
3115 // insert at the end of the corresponding predecessor.
3116 HInstruction* next = NULL;
3117 if (use_value->IsPhi()) {
3118 next = use_value->block()->predecessors()->at(use_index)->end();
3119 } else {
3120 next = HInstruction::cast(use_value);
3121 }
3122 // For constants we try to make the representation change at compile
3123 // time. When a representation change is not possible without loss of
3124 // information we treat constants like normal instructions and insert the
3125 // change instructions for them.
3126 HInstruction* new_value = NULL;
3127 bool is_truncating = use_value->CheckFlag(HValue::kTruncatingToInt32);
3128 bool allow_undefined_as_nan =
3129 use_value->CheckFlag(HValue::kAllowUndefinedAsNaN);
3130 if (value->IsConstant()) {
3131 HConstant* constant = HConstant::cast(value);
3132 // Try to create a new copy of the constant with the new representation.
3133 new_value = (is_truncating && to.IsInteger32())
3134 ? constant->CopyToTruncatedInt32(zone())
3135 : constant->CopyToRepresentation(to, zone());
3136 }
3137
3138 if (new_value == NULL) {
3139 new_value = new(zone()) HChange(value, to,
3140 is_truncating, allow_undefined_as_nan);
3141 }
3142
3143 new_value->InsertBefore(next);
3144 use_value->SetOperandAt(use_index, new_value);
3145 }
3146
3147
3148 void HGraph::InsertRepresentationChangesForValue(HValue* value) {
3149 Representation r = value->representation();
3150 if (r.IsNone()) return;
3151 if (value->HasNoUses()) return;
3152
3153 for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) {
3154 HValue* use_value = it.value();
3155 int use_index = it.index();
3156 Representation req = use_value->RequiredInputRepresentation(use_index);
3157 if (req.IsNone() || req.Equals(r)) continue;
3158 InsertRepresentationChangeForUse(value, use_value, use_index, req);
3159 }
3160 if (value->HasNoUses()) {
3161 ASSERT(value->IsConstant());
3162 value->DeleteAndReplaceWith(NULL);
3163 }
3164
3165 // The only purpose of a HForceRepresentation is to represent the value
3166 // after the (possible) HChange instruction. We make it disappear.
3167 if (value->IsForceRepresentation()) {
3168 value->DeleteAndReplaceWith(HForceRepresentation::cast(value)->value());
3169 }
3170 }
3171
3172
3173 void HGraph::InsertRepresentationChanges() {
3174 HPhase phase("H_Representation changes", this);
3175
3176 // Compute truncation flag for phis: Initially assume that all
3177 // int32-phis allow truncation and iteratively remove the ones that
3178 // are used in an operation that does not allow a truncating
3179 // conversion.
3180 ZoneList<HPhi*> worklist(8, zone());
3181
3182 for (int i = 0; i < phi_list()->length(); i++) {
3183 HPhi* phi = phi_list()->at(i);
3184 if (phi->representation().IsInteger32()) {
3185 phi->SetFlag(HValue::kTruncatingToInt32);
3186 }
3187 }
3188
3189 for (int i = 0; i < phi_list()->length(); i++) {
3190 HPhi* phi = phi_list()->at(i);
3191 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
3192 // If a Phi is used as a non-truncating int32 or as a double,
3193 // clear its "truncating" flag.
3194 HValue* use = it.value();
3195 Representation input_representation =
3196 use->RequiredInputRepresentation(it.index());
3197 if (!input_representation.IsInteger32() ||
3198 !use->CheckFlag(HValue::kTruncatingToInt32)) {
3199 if (FLAG_trace_representation) {
3200 PrintF("#%d Phi is not truncating because of #%d %s\n",
3201 phi->id(), it.value()->id(), it.value()->Mnemonic());
3202 }
3203 phi->ClearFlag(HValue::kTruncatingToInt32);
3204 worklist.Add(phi, zone());
3205 break;
3206 }
3207 }
3208 }
3209
3210 while (!worklist.is_empty()) {
3211 HPhi* current = worklist.RemoveLast();
3212 for (int i = 0; i < current->OperandCount(); ++i) {
3213 HValue* input = current->OperandAt(i);
3214 if (input->IsPhi() &&
3215 input->representation().IsInteger32() &&
3216 input->CheckFlag(HValue::kTruncatingToInt32)) {
3217 if (FLAG_trace_representation) {
3218 PrintF("#%d Phi is not truncating because of #%d %s\n",
3219 input->id(), current->id(), current->Mnemonic());
3220 }
3221 input->ClearFlag(HValue::kTruncatingToInt32);
3222 worklist.Add(HPhi::cast(input), zone());
3223 }
3224 }
3225 }
3226
3227 for (int i = 0; i < blocks_.length(); ++i) {
3228 // Process phi instructions first.
3229 const ZoneList<HPhi*>* phis = blocks_[i]->phis();
3230 for (int j = 0; j < phis->length(); j++) {
3231 InsertRepresentationChangesForValue(phis->at(j));
3232 }
3233
3234 // Process normal instructions.
3235 HInstruction* current = blocks_[i]->first();
3236 while (current != NULL) {
3237 HInstruction* next = current->next();
3238 InsertRepresentationChangesForValue(current);
3239 current = next;
3240 }
3241 }
3242 }
3243
3244
3245 void HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi) { 2677 void HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi) {
3246 if (!phi->CheckFlag(HValue::kAllowUndefinedAsNaN)) return; 2678 if (!phi->CheckFlag(HValue::kAllowUndefinedAsNaN)) return;
3247 phi->ClearFlag(HValue::kAllowUndefinedAsNaN); 2679 phi->ClearFlag(HValue::kAllowUndefinedAsNaN);
3248 for (int i = 0; i < phi->OperandCount(); ++i) { 2680 for (int i = 0; i < phi->OperandCount(); ++i) {
3249 HValue* input = phi->OperandAt(i); 2681 HValue* input = phi->OperandAt(i);
3250 if (input->IsPhi()) { 2682 if (input->IsPhi()) {
3251 RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi::cast(input)); 2683 RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi::cast(input));
3252 } 2684 }
3253 } 2685 }
3254 } 2686 }
3255 2687
3256 2688
3257 void HGraph::MarkDeoptimizeOnUndefined() { 2689 void HGraph::MarkDeoptimizeOnUndefined() {
3258 HPhase phase("H_MarkDeoptimizeOnUndefined", this); 2690 HPhase phase("H_MarkDeoptimizeOnUndefined", this);
3259 // Compute DeoptimizeOnUndefined flag for phis. 2691 // Compute DeoptimizeOnUndefined flag for phis. Any phi that can reach a use
3260 // Any phi that can reach a use with DeoptimizeOnUndefined set must 2692 // with DeoptimizeOnUndefined set must have DeoptimizeOnUndefined set.
3261 // have DeoptimizeOnUndefined set. Currently only HCompareIDAndBranch, with 2693 // Currently only HCompareNumericAndBranch, with double input representation,
3262 // double input representation, has this flag set. 2694 // has this flag set. The flag is used by HChange tagged->double, which must
3263 // The flag is used by HChange tagged->double, which must deoptimize 2695 // deoptimize if one of its uses has this flag set.
3264 // if one of its uses has this flag set.
3265 for (int i = 0; i < phi_list()->length(); i++) { 2696 for (int i = 0; i < phi_list()->length(); i++) {
3266 HPhi* phi = phi_list()->at(i); 2697 HPhi* phi = phi_list()->at(i);
3267 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { 2698 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
3268 HValue* use_value = it.value(); 2699 HValue* use_value = it.value();
3269 if (!use_value->CheckFlag(HValue::kAllowUndefinedAsNaN)) { 2700 if (!use_value->CheckFlag(HValue::kAllowUndefinedAsNaN)) {
3270 RecursivelyMarkPhiDeoptimizeOnUndefined(phi); 2701 RecursivelyMarkPhiDeoptimizeOnUndefined(phi);
3271 break; 2702 break;
3272 } 2703 }
3273 } 2704 }
3274 } 2705 }
3275 } 2706 }
3276 2707
3277 2708
3278 // Discover instructions that can be marked with kUint32 flag allowing
3279 // them to produce full range uint32 values.
3280 class Uint32Analysis BASE_EMBEDDED {
3281 public:
3282 explicit Uint32Analysis(Zone* zone) : zone_(zone), phis_(4, zone) { }
3283
3284 void Analyze(HInstruction* current);
3285
3286 void UnmarkUnsafePhis();
3287
3288 private:
3289 bool IsSafeUint32Use(HValue* val, HValue* use);
3290 bool Uint32UsesAreSafe(HValue* uint32val);
3291 bool CheckPhiOperands(HPhi* phi);
3292 void UnmarkPhi(HPhi* phi, ZoneList<HPhi*>* worklist);
3293
3294 Zone* zone_;
3295 ZoneList<HPhi*> phis_;
3296 };
3297
3298
3299 bool Uint32Analysis::IsSafeUint32Use(HValue* val, HValue* use) {
3300 // Operations that operatate on bits are safe.
3301 if (use->IsBitwise() ||
3302 use->IsShl() ||
3303 use->IsSar() ||
3304 use->IsShr() ||
3305 use->IsBitNot()) {
3306 return true;
3307 } else if (use->IsChange() || use->IsSimulate()) {
3308 // Conversions and deoptimization have special support for unt32.
3309 return true;
3310 } else if (use->IsStoreKeyed()) {
3311 HStoreKeyed* store = HStoreKeyed::cast(use);
3312 if (store->is_external()) {
3313 // Storing a value into an external integer array is a bit level
3314 // operation.
3315 if (store->value() == val) {
3316 // Clamping or a conversion to double should have beed inserted.
3317 ASSERT(store->elements_kind() != EXTERNAL_PIXEL_ELEMENTS);
3318 ASSERT(store->elements_kind() != EXTERNAL_FLOAT_ELEMENTS);
3319 ASSERT(store->elements_kind() != EXTERNAL_DOUBLE_ELEMENTS);
3320 return true;
3321 }
3322 }
3323 }
3324
3325 return false;
3326 }
3327
3328
3329 // Iterate over all uses and verify that they are uint32 safe: either don't
3330 // distinguish between int32 and uint32 due to their bitwise nature or
3331 // have special support for uint32 values.
3332 // Encountered phis are optimisitically treated as safe uint32 uses,
3333 // marked with kUint32 flag and collected in the phis_ list. A separate
3334 // path will be performed later by UnmarkUnsafePhis to clear kUint32 from
3335 // phis that are not actually uint32-safe (it requries fix point iteration).
3336 bool Uint32Analysis::Uint32UsesAreSafe(HValue* uint32val) {
3337 bool collect_phi_uses = false;
3338 for (HUseIterator it(uint32val->uses()); !it.Done(); it.Advance()) {
3339 HValue* use = it.value();
3340
3341 if (use->IsPhi()) {
3342 if (!use->CheckFlag(HInstruction::kUint32)) {
3343 // There is a phi use of this value from a phis that is not yet
3344 // collected in phis_ array. Separate pass is required.
3345 collect_phi_uses = true;
3346 }
3347
3348 // Optimistically treat phis as uint32 safe.
3349 continue;
3350 }
3351
3352 if (!IsSafeUint32Use(uint32val, use)) {
3353 return false;
3354 }
3355 }
3356
3357 if (collect_phi_uses) {
3358 for (HUseIterator it(uint32val->uses()); !it.Done(); it.Advance()) {
3359 HValue* use = it.value();
3360
3361 // There is a phi use of this value from a phis that is not yet
3362 // collected in phis_ array. Separate pass is required.
3363 if (use->IsPhi() && !use->CheckFlag(HInstruction::kUint32)) {
3364 use->SetFlag(HInstruction::kUint32);
3365 phis_.Add(HPhi::cast(use), zone_);
3366 }
3367 }
3368 }
3369
3370 return true;
3371 }
3372
3373
3374 // Analyze instruction and mark it with kUint32 if all its uses are uint32
3375 // safe.
3376 void Uint32Analysis::Analyze(HInstruction* current) {
3377 if (Uint32UsesAreSafe(current)) current->SetFlag(HInstruction::kUint32);
3378 }
3379
3380
3381 // Check if all operands to the given phi are marked with kUint32 flag.
3382 bool Uint32Analysis::CheckPhiOperands(HPhi* phi) {
3383 if (!phi->CheckFlag(HInstruction::kUint32)) {
3384 // This phi is not uint32 safe. No need to check operands.
3385 return false;
3386 }
3387
3388 for (int j = 0; j < phi->OperandCount(); j++) {
3389 HValue* operand = phi->OperandAt(j);
3390 if (!operand->CheckFlag(HInstruction::kUint32)) {
3391 // Lazyly mark constants that fit into uint32 range with kUint32 flag.
3392 if (operand->IsInteger32Constant() &&
3393 operand->GetInteger32Constant() >= 0) {
3394 operand->SetFlag(HInstruction::kUint32);
3395 continue;
3396 }
3397
3398 // This phi is not safe, some operands are not uint32 values.
3399 return false;
3400 }
3401 }
3402
3403 return true;
3404 }
3405
3406
3407 // Remove kUint32 flag from the phi itself and its operands. If any operand
3408 // was a phi marked with kUint32 place it into a worklist for
3409 // transitive clearing of kUint32 flag.
3410 void Uint32Analysis::UnmarkPhi(HPhi* phi, ZoneList<HPhi*>* worklist) {
3411 phi->ClearFlag(HInstruction::kUint32);
3412 for (int j = 0; j < phi->OperandCount(); j++) {
3413 HValue* operand = phi->OperandAt(j);
3414 if (operand->CheckFlag(HInstruction::kUint32)) {
3415 operand->ClearFlag(HInstruction::kUint32);
3416 if (operand->IsPhi()) {
3417 worklist->Add(HPhi::cast(operand), zone_);
3418 }
3419 }
3420 }
3421 }
3422
3423
3424 void Uint32Analysis::UnmarkUnsafePhis() {
3425 // No phis were collected. Nothing to do.
3426 if (phis_.length() == 0) return;
3427
3428 // Worklist used to transitively clear kUint32 from phis that
3429 // are used as arguments to other phis.
3430 ZoneList<HPhi*> worklist(phis_.length(), zone_);
3431
3432 // Phi can be used as a uint32 value if and only if
3433 // all its operands are uint32 values and all its
3434 // uses are uint32 safe.
3435
3436 // Iterate over collected phis and unmark those that
3437 // are unsafe. When unmarking phi unmark its operands
3438 // and add it to the worklist if it is a phi as well.
3439 // Phis that are still marked as safe are shifted down
3440 // so that all safe phis form a prefix of the phis_ array.
3441 int phi_count = 0;
3442 for (int i = 0; i < phis_.length(); i++) {
3443 HPhi* phi = phis_[i];
3444
3445 if (CheckPhiOperands(phi) && Uint32UsesAreSafe(phi)) {
3446 phis_[phi_count++] = phi;
3447 } else {
3448 UnmarkPhi(phi, &worklist);
3449 }
3450 }
3451
3452 // Now phis array contains only those phis that have safe
3453 // non-phi uses. Start transitively clearing kUint32 flag
3454 // from phi operands of discovered non-safe phies until
3455 // only safe phies are left.
3456 while (!worklist.is_empty()) {
3457 while (!worklist.is_empty()) {
3458 HPhi* phi = worklist.RemoveLast();
3459 UnmarkPhi(phi, &worklist);
3460 }
3461
3462 // Check if any operands to safe phies were unmarked
3463 // turning a safe phi into unsafe. The same value
3464 // can flow into several phis.
3465 int new_phi_count = 0;
3466 for (int i = 0; i < phi_count; i++) {
3467 HPhi* phi = phis_[i];
3468
3469 if (CheckPhiOperands(phi)) {
3470 phis_[new_phi_count++] = phi;
3471 } else {
3472 UnmarkPhi(phi, &worklist);
3473 }
3474 }
3475 phi_count = new_phi_count;
3476 }
3477 }
3478
3479
3480 void HGraph::ComputeSafeUint32Operations() {
3481 HPhase phase("H_Compute safe UInt32 operations", this);
3482 if (uint32_instructions_ == NULL) return;
3483
3484 Uint32Analysis analysis(zone());
3485 for (int i = 0; i < uint32_instructions_->length(); ++i) {
3486 HInstruction* current = uint32_instructions_->at(i);
3487 if (current->IsLinked() && current->representation().IsInteger32()) {
3488 analysis.Analyze(current);
3489 }
3490 }
3491
3492 // Some phis might have been optimistically marked with kUint32 flag.
3493 // Remove this flag from those phis that are unsafe and propagate
3494 // this information transitively potentially clearing kUint32 flag
3495 // from some non-phi operations that are used as operands to unsafe phis.
3496 analysis.UnmarkUnsafePhis();
3497 }
3498
3499
3500 void HGraph::ComputeMinusZeroChecks() { 2709 void HGraph::ComputeMinusZeroChecks() {
3501 HPhase phase("H_Compute minus zero checks", this); 2710 HPhase phase("H_Compute minus zero checks", this);
3502 BitVector visited(GetMaximumValueID(), zone()); 2711 BitVector visited(GetMaximumValueID(), zone());
3503 for (int i = 0; i < blocks_.length(); ++i) { 2712 for (int i = 0; i < blocks_.length(); ++i) {
3504 for (HInstruction* current = blocks_[i]->first(); 2713 for (HInstructionIterator it(blocks_[i]); !it.Done(); it.Advance()) {
3505 current != NULL; 2714 HInstruction* current = it.Current();
3506 current = current->next()) {
3507 if (current->IsChange()) { 2715 if (current->IsChange()) {
3508 HChange* change = HChange::cast(current); 2716 HChange* change = HChange::cast(current);
3509 // Propagate flags for negative zero checks upwards from conversions 2717 // Propagate flags for negative zero checks upwards from conversions
3510 // int32-to-tagged and int32-to-double. 2718 // int32-to-tagged and int32-to-double.
3511 Representation from = change->value()->representation(); 2719 Representation from = change->value()->representation();
3512 ASSERT(from.Equals(change->from())); 2720 ASSERT(from.Equals(change->from()));
3513 if (from.IsInteger32()) { 2721 if (from.IsInteger32()) {
3514 ASSERT(change->to().IsTagged() || 2722 ASSERT(change->to().IsTagged() ||
3515 change->to().IsDouble() || 2723 change->to().IsDouble() ||
3516 change->to().IsSmi()); 2724 change->to().IsSmi());
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
3778 builder->current_block()->Goto(if_true(), builder->function_state()); 2986 builder->current_block()->Goto(if_true(), builder->function_state());
3779 } else { 2987 } else {
3780 builder->current_block()->Goto(if_false(), builder->function_state()); 2988 builder->current_block()->Goto(if_false(), builder->function_state());
3781 } 2989 }
3782 builder->set_current_block(NULL); 2990 builder->set_current_block(NULL);
3783 return; 2991 return;
3784 } 2992 }
3785 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); 2993 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
3786 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); 2994 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
3787 ToBooleanStub::Types expected(condition()->to_boolean_types()); 2995 ToBooleanStub::Types expected(condition()->to_boolean_types());
3788 HBranch* test = new(zone()) HBranch(value, empty_true, empty_false, expected); 2996 HBranch* test = new(zone()) HBranch(value, expected, empty_true, empty_false);
3789 builder->current_block()->Finish(test); 2997 builder->current_block()->Finish(test);
3790 2998
3791 empty_true->Goto(if_true(), builder->function_state()); 2999 empty_true->Goto(if_true(), builder->function_state());
3792 empty_false->Goto(if_false(), builder->function_state()); 3000 empty_false->Goto(if_false(), builder->function_state());
3793 builder->set_current_block(NULL); 3001 builder->set_current_block(NULL);
3794 } 3002 }
3795 3003
3796 3004
3797 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts. 3005 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts.
3798 #define CHECK_BAILOUT(call) \ 3006 #define CHECK_BAILOUT(call) \
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
3846 void HOptimizedGraphBuilder::VisitForControl(Expression* expr, 3054 void HOptimizedGraphBuilder::VisitForControl(Expression* expr,
3847 HBasicBlock* true_block, 3055 HBasicBlock* true_block,
3848 HBasicBlock* false_block) { 3056 HBasicBlock* false_block) {
3849 TestContext for_test(this, expr, true_block, false_block); 3057 TestContext for_test(this, expr, true_block, false_block);
3850 Visit(expr); 3058 Visit(expr);
3851 } 3059 }
3852 3060
3853 3061
3854 void HOptimizedGraphBuilder::VisitArgument(Expression* expr) { 3062 void HOptimizedGraphBuilder::VisitArgument(Expression* expr) {
3855 CHECK_ALIVE(VisitForValue(expr)); 3063 CHECK_ALIVE(VisitForValue(expr));
3856 Push(AddInstruction(new(zone()) HPushArgument(Pop()))); 3064 Push(Add<HPushArgument>(Pop()));
3857 } 3065 }
3858 3066
3859 3067
3860 void HOptimizedGraphBuilder::VisitArgumentList( 3068 void HOptimizedGraphBuilder::VisitArgumentList(
3861 ZoneList<Expression*>* arguments) { 3069 ZoneList<Expression*>* arguments) {
3862 for (int i = 0; i < arguments->length(); i++) { 3070 for (int i = 0; i < arguments->length(); i++) {
3863 CHECK_ALIVE(VisitArgument(arguments->at(i))); 3071 CHECK_ALIVE(VisitArgument(arguments->at(i)));
3864 } 3072 }
3865 } 3073 }
3866 3074
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
3912 3120
3913 // Handle implicit declaration of the function name in named function 3121 // Handle implicit declaration of the function name in named function
3914 // expressions before other declarations. 3122 // expressions before other declarations.
3915 if (scope->is_function_scope() && scope->function() != NULL) { 3123 if (scope->is_function_scope() && scope->function() != NULL) {
3916 VisitVariableDeclaration(scope->function()); 3124 VisitVariableDeclaration(scope->function());
3917 } 3125 }
3918 VisitDeclarations(scope->declarations()); 3126 VisitDeclarations(scope->declarations());
3919 AddSimulate(BailoutId::Declarations()); 3127 AddSimulate(BailoutId::Declarations());
3920 3128
3921 HValue* context = environment()->LookupContext(); 3129 HValue* context = environment()->LookupContext();
3922 AddInstruction( 3130 Add<HStackCheck>(context, HStackCheck::kFunctionEntry);
3923 new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry));
3924 3131
3925 VisitStatements(current_info()->function()->body()); 3132 VisitStatements(current_info()->function()->body());
3926 if (HasStackOverflow()) return false; 3133 if (HasStackOverflow()) return false;
3927 3134
3928 if (current_block() != NULL) { 3135 if (current_block() != NULL) {
3929 AddReturn(graph()->GetConstantUndefined()); 3136 AddReturn(graph()->GetConstantUndefined());
3930 set_current_block(NULL); 3137 set_current_block(NULL);
3931 } 3138 }
3932 3139
3933 // If the checksum of the number of type info changes is the same as the 3140 // If the checksum of the number of type info changes is the same as the
3934 // last time this function was compiled, then this recompile is likely not 3141 // last time this function was compiled, then this recompile is likely not
3935 // due to missing/inadequate type feedback, but rather too aggressive 3142 // due to missing/inadequate type feedback, but rather too aggressive
3936 // optimization. Disable optimistic LICM in that case. 3143 // optimization. Disable optimistic LICM in that case.
3937 Handle<Code> unoptimized_code(current_info()->shared_info()->code()); 3144 Handle<Code> unoptimized_code(current_info()->shared_info()->code());
3938 ASSERT(unoptimized_code->kind() == Code::FUNCTION); 3145 ASSERT(unoptimized_code->kind() == Code::FUNCTION);
3939 Handle<TypeFeedbackInfo> type_info( 3146 Handle<TypeFeedbackInfo> type_info(
3940 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); 3147 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
3941 int checksum = type_info->own_type_change_checksum(); 3148 int checksum = type_info->own_type_change_checksum();
3942 int composite_checksum = graph()->update_type_change_checksum(checksum); 3149 int composite_checksum = graph()->update_type_change_checksum(checksum);
3943 graph()->set_use_optimistic_licm( 3150 graph()->set_use_optimistic_licm(
3944 !type_info->matches_inlined_type_change_checksum(composite_checksum)); 3151 !type_info->matches_inlined_type_change_checksum(composite_checksum));
3945 type_info->set_inlined_type_change_checksum(composite_checksum); 3152 type_info->set_inlined_type_change_checksum(composite_checksum);
3946 3153
3154 // Perform any necessary OSR-specific cleanups or changes to the graph.
3155 osr_->FinishGraph();
3156
3947 return true; 3157 return true;
3948 } 3158 }
3949 3159
3950 3160
3951 bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) { 3161 bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) {
3952 *bailout_reason = SmartArrayPointer<char>(); 3162 *bailout_reason = SmartArrayPointer<char>();
3953 OrderBlocks(); 3163 OrderBlocks();
3954 AssignDominators(); 3164 AssignDominators();
3955 3165
3956 // We need to create a HConstant "zero" now so that GVN will fold every 3166 // We need to create a HConstant "zero" now so that GVN will fold every
(...skipping 10 matching lines...) Expand all
3967 if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) { 3177 if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) {
3968 Run<HEnvironmentLivenessAnalysisPhase>(); 3178 Run<HEnvironmentLivenessAnalysisPhase>();
3969 } 3179 }
3970 3180
3971 PropagateDeoptimizingMark(); 3181 PropagateDeoptimizingMark();
3972 if (!CheckConstPhiUses()) { 3182 if (!CheckConstPhiUses()) {
3973 *bailout_reason = SmartArrayPointer<char>(StrDup( 3183 *bailout_reason = SmartArrayPointer<char>(StrDup(
3974 "Unsupported phi use of const variable")); 3184 "Unsupported phi use of const variable"));
3975 return false; 3185 return false;
3976 } 3186 }
3977 EliminateRedundantPhis(); 3187 Run<HRedundantPhiEliminationPhase>();
3978 if (!CheckArgumentsPhiUses()) { 3188 if (!CheckArgumentsPhiUses()) {
3979 *bailout_reason = SmartArrayPointer<char>(StrDup( 3189 *bailout_reason = SmartArrayPointer<char>(StrDup(
3980 "Unsupported phi use of arguments")); 3190 "Unsupported phi use of arguments"));
3981 return false; 3191 return false;
3982 } 3192 }
3983 3193
3984 // Remove dead code and phis 3194 // Remove dead code and phis
3985 if (FLAG_dead_code_elimination) { 3195 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
3986 DeadCodeElimination("H_Eliminate early dead code");
3987 }
3988 CollectPhis(); 3196 CollectPhis();
3989 3197
3990 if (has_osr_loop_entry()) { 3198 if (has_osr()) osr()->FinishOsrValues();
3991 const ZoneList<HPhi*>* phis = osr_loop_entry()->phis();
3992 for (int j = 0; j < phis->length(); j++) {
3993 HPhi* phi = phis->at(j);
3994 osr_values()->at(phi->merged_index())->set_incoming_value(phi);
3995 }
3996 }
3997 3199
3998 HInferRepresentation rep(this); 3200 Run<HInferRepresentationPhase>();
3999 rep.Analyze();
4000 3201
4001 // Remove HSimulate instructions that have turned out not to be needed 3202 // Remove HSimulate instructions that have turned out not to be needed
4002 // after all by folding them into the following HSimulate. 3203 // after all by folding them into the following HSimulate.
4003 // This must happen after inferring representations. 3204 // This must happen after inferring representations.
4004 MergeRemovableSimulates(); 3205 MergeRemovableSimulates();
4005 3206
4006 MarkDeoptimizeOnUndefined(); 3207 MarkDeoptimizeOnUndefined();
4007 InsertRepresentationChanges(); 3208 Run<HRepresentationChangesPhase>();
4008 3209
4009 InitializeInferredTypes(); 3210 Run<HInferTypesPhase>();
4010 3211
4011 // Must be performed before canonicalization to ensure that Canonicalize 3212 // Must be performed before canonicalization to ensure that Canonicalize
4012 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with 3213 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with
4013 // zero. 3214 // zero.
4014 if (FLAG_opt_safe_uint32_operations) ComputeSafeUint32Operations(); 3215 if (FLAG_opt_safe_uint32_operations) Run<HUint32AnalysisPhase>();
4015 3216
4016 if (FLAG_use_canonicalizing) Canonicalize(); 3217 if (FLAG_use_canonicalizing) Canonicalize();
4017 3218
3219 if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>();
3220
4018 if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>(); 3221 if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>();
4019 3222
4020 if (FLAG_use_range) { 3223 if (FLAG_use_range) Run<HRangeAnalysisPhase>();
4021 HRangeAnalysis rangeAnalysis(this); 3224
4022 rangeAnalysis.Analyze();
4023 }
4024 ComputeMinusZeroChecks(); 3225 ComputeMinusZeroChecks();
4025 3226
4026 // Eliminate redundant stack checks on backwards branches. 3227 // Eliminate redundant stack checks on backwards branches.
4027 HStackCheckEliminator sce(this); 3228 Run<HStackCheckEliminationPhase>();
4028 sce.Process();
4029 3229
4030 if (FLAG_idefs) SetupInformativeDefinitions(); 3230 if (FLAG_idefs) SetupInformativeDefinitions();
4031 if (FLAG_array_bounds_checks_elimination && !FLAG_idefs) { 3231 if (FLAG_array_bounds_checks_elimination && !FLAG_idefs) {
4032 EliminateRedundantBoundsChecks(); 3232 Run<HBoundsCheckEliminationPhase>();
4033 } 3233 }
4034 if (FLAG_array_index_dehoisting) DehoistSimpleArrayIndexComputations(); 3234 if (FLAG_array_index_dehoisting) DehoistSimpleArrayIndexComputations();
4035 if (FLAG_dead_code_elimination) { 3235 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
4036 DeadCodeElimination("H_Eliminate late dead code");
4037 }
4038 3236
4039 RestoreActualValues(); 3237 RestoreActualValues();
4040 3238
4041 return true; 3239 return true;
4042 } 3240 }
4043 3241
4044 3242
4045 void HGraph::SetupInformativeDefinitionsInBlock(HBasicBlock* block) { 3243 void HGraph::SetupInformativeDefinitionsInBlock(HBasicBlock* block) {
4046 for (int phi_index = 0; phi_index < block->phis()->length(); phi_index++) { 3244 for (int phi_index = 0; phi_index < block->phis()->length(); phi_index++) {
4047 HPhi* phi = block->phis()->at(phi_index); 3245 HPhi* phi = block->phis()->at(phi_index);
4048 phi->AddInformativeDefinitions(); 3246 phi->AddInformativeDefinitions();
4049 phi->SetFlag(HValue::kIDefsProcessingDone); 3247 phi->SetFlag(HValue::kIDefsProcessingDone);
4050 // We do not support phis that "redefine just one operand". 3248 // We do not support phis that "redefine just one operand".
4051 ASSERT(!phi->IsInformativeDefinition()); 3249 ASSERT(!phi->IsInformativeDefinition());
4052 } 3250 }
4053 3251
4054 for (HInstruction* i = block->first(); i != NULL; i = i->next()) { 3252 for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
3253 HInstruction* i = it.Current();
4055 i->AddInformativeDefinitions(); 3254 i->AddInformativeDefinitions();
4056 i->SetFlag(HValue::kIDefsProcessingDone); 3255 i->SetFlag(HValue::kIDefsProcessingDone);
4057 i->UpdateRedefinedUsesWhileSettingUpInformativeDefinitions(); 3256 i->UpdateRedefinedUsesWhileSettingUpInformativeDefinitions();
4058 } 3257 }
4059 } 3258 }
4060 3259
4061 3260
4062 // This method is recursive, so if its stack frame is large it could 3261 // This method is recursive, so if its stack frame is large it could
4063 // cause a stack overflow. 3262 // cause a stack overflow.
4064 // To keep the individual stack frames small we do the actual work inside 3263 // To keep the individual stack frames small we do the actual work inside
4065 // SetupInformativeDefinitionsInBlock(); 3264 // SetupInformativeDefinitionsInBlock();
4066 void HGraph::SetupInformativeDefinitionsRecursively(HBasicBlock* block) { 3265 void HGraph::SetupInformativeDefinitionsRecursively(HBasicBlock* block) {
4067 SetupInformativeDefinitionsInBlock(block); 3266 SetupInformativeDefinitionsInBlock(block);
4068 for (int i = 0; i < block->dominated_blocks()->length(); ++i) { 3267 for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
4069 SetupInformativeDefinitionsRecursively(block->dominated_blocks()->at(i)); 3268 SetupInformativeDefinitionsRecursively(block->dominated_blocks()->at(i));
4070 } 3269 }
4071 3270
4072 for (HInstruction* i = block->first(); i != NULL; i = i->next()) { 3271 for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
3272 HInstruction* i = it.Current();
4073 if (i->IsBoundsCheck()) { 3273 if (i->IsBoundsCheck()) {
4074 HBoundsCheck* check = HBoundsCheck::cast(i); 3274 HBoundsCheck* check = HBoundsCheck::cast(i);
4075 check->ApplyIndexChange(); 3275 check->ApplyIndexChange();
4076 } 3276 }
4077 } 3277 }
4078 } 3278 }
4079 3279
4080 3280
4081 void HGraph::SetupInformativeDefinitions() { 3281 void HGraph::SetupInformativeDefinitions() {
4082 HPhase phase("H_Setup informative definitions", this); 3282 HPhase phase("H_Setup informative definitions", this);
4083 SetupInformativeDefinitionsRecursively(entry_block()); 3283 SetupInformativeDefinitionsRecursively(entry_block());
4084 } 3284 }
4085 3285
4086 3286
4087 // We try to "factor up" HBoundsCheck instructions towards the root of the
4088 // dominator tree.
4089 // For now we handle checks where the index is like "exp + int32value".
4090 // If in the dominator tree we check "exp + v1" and later (dominated)
4091 // "exp + v2", if v2 <= v1 we can safely remove the second check, and if
4092 // v2 > v1 we can use v2 in the 1st check and again remove the second.
4093 // To do so we keep a dictionary of all checks where the key if the pair
4094 // "exp, length".
4095 // The class BoundsCheckKey represents this key.
4096 class BoundsCheckKey : public ZoneObject {
4097 public:
4098 HValue* IndexBase() const { return index_base_; }
4099 HValue* Length() const { return length_; }
4100
4101 uint32_t Hash() {
4102 return static_cast<uint32_t>(index_base_->Hashcode() ^ length_->Hashcode());
4103 }
4104
4105 static BoundsCheckKey* Create(Zone* zone,
4106 HBoundsCheck* check,
4107 int32_t* offset) {
4108 if (!check->index()->representation().IsSmiOrInteger32()) return NULL;
4109
4110 HValue* index_base = NULL;
4111 HConstant* constant = NULL;
4112 bool is_sub = false;
4113
4114 if (check->index()->IsAdd()) {
4115 HAdd* index = HAdd::cast(check->index());
4116 if (index->left()->IsConstant()) {
4117 constant = HConstant::cast(index->left());
4118 index_base = index->right();
4119 } else if (index->right()->IsConstant()) {
4120 constant = HConstant::cast(index->right());
4121 index_base = index->left();
4122 }
4123 } else if (check->index()->IsSub()) {
4124 HSub* index = HSub::cast(check->index());
4125 is_sub = true;
4126 if (index->left()->IsConstant()) {
4127 constant = HConstant::cast(index->left());
4128 index_base = index->right();
4129 } else if (index->right()->IsConstant()) {
4130 constant = HConstant::cast(index->right());
4131 index_base = index->left();
4132 }
4133 }
4134
4135 if (constant != NULL && constant->HasInteger32Value()) {
4136 *offset = is_sub ? - constant->Integer32Value()
4137 : constant->Integer32Value();
4138 } else {
4139 *offset = 0;
4140 index_base = check->index();
4141 }
4142
4143 return new(zone) BoundsCheckKey(index_base, check->length());
4144 }
4145
4146 private:
4147 BoundsCheckKey(HValue* index_base, HValue* length)
4148 : index_base_(index_base),
4149 length_(length) { }
4150
4151 HValue* index_base_;
4152 HValue* length_;
4153 };
4154
4155
4156 // Data about each HBoundsCheck that can be eliminated or moved.
4157 // It is the "value" in the dictionary indexed by "base-index, length"
4158 // (the key is BoundsCheckKey).
4159 // We scan the code with a dominator tree traversal.
4160 // Traversing the dominator tree we keep a stack (implemented as a singly
4161 // linked list) of "data" for each basic block that contains a relevant check
4162 // with the same key (the dictionary holds the head of the list).
4163 // We also keep all the "data" created for a given basic block in a list, and
4164 // use it to "clean up" the dictionary when backtracking in the dominator tree
4165 // traversal.
4166 // Doing this each dictionary entry always directly points to the check that
4167 // is dominating the code being examined now.
4168 // We also track the current "offset" of the index expression and use it to
4169 // decide if any check is already "covered" (so it can be removed) or not.
4170 class BoundsCheckBbData: public ZoneObject {
4171 public:
4172 BoundsCheckKey* Key() const { return key_; }
4173 int32_t LowerOffset() const { return lower_offset_; }
4174 int32_t UpperOffset() const { return upper_offset_; }
4175 HBasicBlock* BasicBlock() const { return basic_block_; }
4176 HBoundsCheck* LowerCheck() const { return lower_check_; }
4177 HBoundsCheck* UpperCheck() const { return upper_check_; }
4178 BoundsCheckBbData* NextInBasicBlock() const { return next_in_bb_; }
4179 BoundsCheckBbData* FatherInDominatorTree() const { return father_in_dt_; }
4180
4181 bool OffsetIsCovered(int32_t offset) const {
4182 return offset >= LowerOffset() && offset <= UpperOffset();
4183 }
4184
4185 bool HasSingleCheck() { return lower_check_ == upper_check_; }
4186
4187 // The goal of this method is to modify either upper_offset_ or
4188 // lower_offset_ so that also new_offset is covered (the covered
4189 // range grows).
4190 //
4191 // The precondition is that new_check follows UpperCheck() and
4192 // LowerCheck() in the same basic block, and that new_offset is not
4193 // covered (otherwise we could simply remove new_check).
4194 //
4195 // If HasSingleCheck() is true then new_check is added as "second check"
4196 // (either upper or lower; note that HasSingleCheck() becomes false).
4197 // Otherwise one of the current checks is modified so that it also covers
4198 // new_offset, and new_check is removed.
4199 //
4200 // If the check cannot be modified because the context is unknown it
4201 // returns false, otherwise it returns true.
4202 bool CoverCheck(HBoundsCheck* new_check,
4203 int32_t new_offset) {
4204 ASSERT(new_check->index()->representation().IsSmiOrInteger32());
4205 bool keep_new_check = false;
4206
4207 if (new_offset > upper_offset_) {
4208 upper_offset_ = new_offset;
4209 if (HasSingleCheck()) {
4210 keep_new_check = true;
4211 upper_check_ = new_check;
4212 } else {
4213 bool result = BuildOffsetAdd(upper_check_,
4214 &added_upper_index_,
4215 &added_upper_offset_,
4216 Key()->IndexBase(),
4217 new_check->index()->representation(),
4218 new_offset);
4219 if (!result) return false;
4220 upper_check_->ReplaceAllUsesWith(upper_check_->index());
4221 upper_check_->SetOperandAt(0, added_upper_index_);
4222 }
4223 } else if (new_offset < lower_offset_) {
4224 lower_offset_ = new_offset;
4225 if (HasSingleCheck()) {
4226 keep_new_check = true;
4227 lower_check_ = new_check;
4228 } else {
4229 bool result = BuildOffsetAdd(lower_check_,
4230 &added_lower_index_,
4231 &added_lower_offset_,
4232 Key()->IndexBase(),
4233 new_check->index()->representation(),
4234 new_offset);
4235 if (!result) return false;
4236 lower_check_->ReplaceAllUsesWith(lower_check_->index());
4237 lower_check_->SetOperandAt(0, added_lower_index_);
4238 }
4239 } else {
4240 ASSERT(false);
4241 }
4242
4243 if (!keep_new_check) {
4244 new_check->DeleteAndReplaceWith(new_check->ActualValue());
4245 }
4246
4247 return true;
4248 }
4249
4250 void RemoveZeroOperations() {
4251 RemoveZeroAdd(&added_lower_index_, &added_lower_offset_);
4252 RemoveZeroAdd(&added_upper_index_, &added_upper_offset_);
4253 }
4254
4255 BoundsCheckBbData(BoundsCheckKey* key,
4256 int32_t lower_offset,
4257 int32_t upper_offset,
4258 HBasicBlock* bb,
4259 HBoundsCheck* lower_check,
4260 HBoundsCheck* upper_check,
4261 BoundsCheckBbData* next_in_bb,
4262 BoundsCheckBbData* father_in_dt)
4263 : key_(key),
4264 lower_offset_(lower_offset),
4265 upper_offset_(upper_offset),
4266 basic_block_(bb),
4267 lower_check_(lower_check),
4268 upper_check_(upper_check),
4269 added_lower_index_(NULL),
4270 added_lower_offset_(NULL),
4271 added_upper_index_(NULL),
4272 added_upper_offset_(NULL),
4273 next_in_bb_(next_in_bb),
4274 father_in_dt_(father_in_dt) { }
4275
4276 private:
4277 BoundsCheckKey* key_;
4278 int32_t lower_offset_;
4279 int32_t upper_offset_;
4280 HBasicBlock* basic_block_;
4281 HBoundsCheck* lower_check_;
4282 HBoundsCheck* upper_check_;
4283 HInstruction* added_lower_index_;
4284 HConstant* added_lower_offset_;
4285 HInstruction* added_upper_index_;
4286 HConstant* added_upper_offset_;
4287 BoundsCheckBbData* next_in_bb_;
4288 BoundsCheckBbData* father_in_dt_;
4289
4290 // Given an existing add instruction and a bounds check it tries to
4291 // find the current context (either of the add or of the check index).
4292 HValue* IndexContext(HInstruction* add, HBoundsCheck* check) {
4293 if (add != NULL && add->IsAdd()) {
4294 return HAdd::cast(add)->context();
4295 }
4296 if (check->index()->IsBinaryOperation()) {
4297 return HBinaryOperation::cast(check->index())->context();
4298 }
4299 return NULL;
4300 }
4301
4302 // This function returns false if it cannot build the add because the
4303 // current context cannot be determined.
4304 bool BuildOffsetAdd(HBoundsCheck* check,
4305 HInstruction** add,
4306 HConstant** constant,
4307 HValue* original_value,
4308 Representation representation,
4309 int32_t new_offset) {
4310 HValue* index_context = IndexContext(*add, check);
4311 if (index_context == NULL) return false;
4312
4313 HConstant* new_constant = new(BasicBlock()->zone()) HConstant(
4314 new_offset, representation);
4315 if (*add == NULL) {
4316 new_constant->InsertBefore(check);
4317 (*add) = HAdd::New(
4318 BasicBlock()->zone(), index_context, original_value, new_constant);
4319 (*add)->AssumeRepresentation(representation);
4320 (*add)->InsertBefore(check);
4321 } else {
4322 new_constant->InsertBefore(*add);
4323 (*constant)->DeleteAndReplaceWith(new_constant);
4324 }
4325 *constant = new_constant;
4326 return true;
4327 }
4328
4329 void RemoveZeroAdd(HInstruction** add, HConstant** constant) {
4330 if (*add != NULL && (*add)->IsAdd() && (*constant)->Integer32Value() == 0) {
4331 (*add)->DeleteAndReplaceWith(HAdd::cast(*add)->left());
4332 (*constant)->DeleteAndReplaceWith(NULL);
4333 }
4334 }
4335 };
4336
4337
4338 static bool BoundsCheckKeyMatch(void* key1, void* key2) {
4339 BoundsCheckKey* k1 = static_cast<BoundsCheckKey*>(key1);
4340 BoundsCheckKey* k2 = static_cast<BoundsCheckKey*>(key2);
4341 return k1->IndexBase() == k2->IndexBase() && k1->Length() == k2->Length();
4342 }
4343
4344
4345 class BoundsCheckTable : private ZoneHashMap {
4346 public:
4347 BoundsCheckBbData** LookupOrInsert(BoundsCheckKey* key, Zone* zone) {
4348 return reinterpret_cast<BoundsCheckBbData**>(
4349 &(Lookup(key, key->Hash(), true, ZoneAllocationPolicy(zone))->value));
4350 }
4351
4352 void Insert(BoundsCheckKey* key, BoundsCheckBbData* data, Zone* zone) {
4353 Lookup(key, key->Hash(), true, ZoneAllocationPolicy(zone))->value = data;
4354 }
4355
4356 void Delete(BoundsCheckKey* key) {
4357 Remove(key, key->Hash());
4358 }
4359
4360 explicit BoundsCheckTable(Zone* zone)
4361 : ZoneHashMap(BoundsCheckKeyMatch, ZoneHashMap::kDefaultHashMapCapacity,
4362 ZoneAllocationPolicy(zone)) { }
4363 };
4364
4365
4366 // Eliminates checks in bb and recursively in the dominated blocks.
4367 // Also replace the results of check instructions with the original value, if
4368 // the result is used. This is safe now, since we don't do code motion after
4369 // this point. It enables better register allocation since the value produced
4370 // by check instructions is really a copy of the original value.
4371 void HGraph::EliminateRedundantBoundsChecks(HBasicBlock* bb,
4372 BoundsCheckTable* table) {
4373 BoundsCheckBbData* bb_data_list = NULL;
4374
4375 for (HInstruction* i = bb->first(); i != NULL; i = i->next()) {
4376 if (!i->IsBoundsCheck()) continue;
4377
4378 HBoundsCheck* check = HBoundsCheck::cast(i);
4379 int32_t offset;
4380 BoundsCheckKey* key =
4381 BoundsCheckKey::Create(zone(), check, &offset);
4382 if (key == NULL) continue;
4383 BoundsCheckBbData** data_p = table->LookupOrInsert(key, zone());
4384 BoundsCheckBbData* data = *data_p;
4385 if (data == NULL) {
4386 bb_data_list = new(zone()) BoundsCheckBbData(key,
4387 offset,
4388 offset,
4389 bb,
4390 check,
4391 check,
4392 bb_data_list,
4393 NULL);
4394 *data_p = bb_data_list;
4395 } else if (data->OffsetIsCovered(offset)) {
4396 check->DeleteAndReplaceWith(check->ActualValue());
4397 } else if (data->BasicBlock() != bb ||
4398 !data->CoverCheck(check, offset)) {
4399 // If the check is in the current BB we try to modify it by calling
4400 // "CoverCheck", but if also that fails we record the current offsets
4401 // in a new data instance because from now on they are covered.
4402 int32_t new_lower_offset = offset < data->LowerOffset()
4403 ? offset
4404 : data->LowerOffset();
4405 int32_t new_upper_offset = offset > data->UpperOffset()
4406 ? offset
4407 : data->UpperOffset();
4408 bb_data_list = new(zone()) BoundsCheckBbData(key,
4409 new_lower_offset,
4410 new_upper_offset,
4411 bb,
4412 data->LowerCheck(),
4413 data->UpperCheck(),
4414 bb_data_list,
4415 data);
4416 table->Insert(key, bb_data_list, zone());
4417 }
4418 }
4419
4420 for (int i = 0; i < bb->dominated_blocks()->length(); ++i) {
4421 EliminateRedundantBoundsChecks(bb->dominated_blocks()->at(i), table);
4422 }
4423
4424 for (BoundsCheckBbData* data = bb_data_list;
4425 data != NULL;
4426 data = data->NextInBasicBlock()) {
4427 data->RemoveZeroOperations();
4428 if (data->FatherInDominatorTree()) {
4429 table->Insert(data->Key(), data->FatherInDominatorTree(), zone());
4430 } else {
4431 table->Delete(data->Key());
4432 }
4433 }
4434 }
4435
4436
4437 void HGraph::EliminateRedundantBoundsChecks() {
4438 HPhase phase("H_Eliminate bounds checks", this);
4439 BoundsCheckTable checks_table(zone());
4440 EliminateRedundantBoundsChecks(entry_block(), &checks_table);
4441 }
4442
4443
4444 static void DehoistArrayIndex(ArrayInstructionInterface* array_operation) { 3287 static void DehoistArrayIndex(ArrayInstructionInterface* array_operation) {
4445 HValue* index = array_operation->GetKey()->ActualValue(); 3288 HValue* index = array_operation->GetKey()->ActualValue();
4446 if (!index->representation().IsSmiOrInteger32()) return; 3289 if (!index->representation().IsSmiOrInteger32()) return;
4447 3290
4448 HConstant* constant; 3291 HConstant* constant;
4449 HValue* subexpression; 3292 HValue* subexpression;
4450 int32_t sign; 3293 int32_t sign;
4451 if (index->IsAdd()) { 3294 if (index->IsAdd()) {
4452 sign = 1; 3295 sign = 1;
4453 HAdd* add = HAdd::cast(index); 3296 HAdd* add = HAdd::cast(index);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
4487 } 3330 }
4488 ASSERT(value >= 0); 3331 ASSERT(value >= 0);
4489 array_operation->SetIndexOffset(static_cast<uint32_t>(value)); 3332 array_operation->SetIndexOffset(static_cast<uint32_t>(value));
4490 array_operation->SetDehoisted(true); 3333 array_operation->SetDehoisted(true);
4491 } 3334 }
4492 3335
4493 3336
4494 void HGraph::DehoistSimpleArrayIndexComputations() { 3337 void HGraph::DehoistSimpleArrayIndexComputations() {
4495 HPhase phase("H_Dehoist index computations", this); 3338 HPhase phase("H_Dehoist index computations", this);
4496 for (int i = 0; i < blocks()->length(); ++i) { 3339 for (int i = 0; i < blocks()->length(); ++i) {
4497 for (HInstruction* instr = blocks()->at(i)->first(); 3340 for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
4498 instr != NULL; 3341 HInstruction* instr = it.Current();
4499 instr = instr->next()) {
4500 ArrayInstructionInterface* array_instruction = NULL; 3342 ArrayInstructionInterface* array_instruction = NULL;
4501 if (instr->IsLoadKeyed()) { 3343 if (instr->IsLoadKeyed()) {
4502 HLoadKeyed* op = HLoadKeyed::cast(instr); 3344 HLoadKeyed* op = HLoadKeyed::cast(instr);
4503 array_instruction = static_cast<ArrayInstructionInterface*>(op); 3345 array_instruction = static_cast<ArrayInstructionInterface*>(op);
4504 } else if (instr->IsStoreKeyed()) { 3346 } else if (instr->IsStoreKeyed()) {
4505 HStoreKeyed* op = HStoreKeyed::cast(instr); 3347 HStoreKeyed* op = HStoreKeyed::cast(instr);
4506 array_instruction = static_cast<ArrayInstructionInterface*>(op); 3348 array_instruction = static_cast<ArrayInstructionInterface*>(op);
4507 } else { 3349 } else {
4508 continue; 3350 continue;
4509 } 3351 }
4510 DehoistArrayIndex(array_instruction); 3352 DehoistArrayIndex(array_instruction);
4511 } 3353 }
4512 } 3354 }
4513 } 3355 }
4514 3356
4515 3357
4516 void HGraph::DeadCodeElimination(const char* phase_name) {
4517 HPhase phase(phase_name, this);
4518 MarkLiveInstructions();
4519 RemoveDeadInstructions();
4520 }
4521
4522
4523 void HGraph::MarkLiveInstructions() {
4524 ZoneList<HValue*> worklist(blocks_.length(), zone());
4525
4526 // Mark initial root instructions for dead code elimination.
4527 for (int i = 0; i < blocks()->length(); ++i) {
4528 HBasicBlock* block = blocks()->at(i);
4529 for (HInstruction* instr = block->first();
4530 instr != NULL;
4531 instr = instr->next()) {
4532 if (instr->CannotBeEliminated()) MarkLive(NULL, instr, &worklist);
4533 }
4534 for (int j = 0; j < block->phis()->length(); j++) {
4535 HPhi* phi = block->phis()->at(j);
4536 if (phi->CannotBeEliminated()) MarkLive(NULL, phi, &worklist);
4537 }
4538 }
4539
4540 // Transitively mark all inputs of live instructions live.
4541 while (!worklist.is_empty()) {
4542 HValue* instr = worklist.RemoveLast();
4543 for (int i = 0; i < instr->OperandCount(); ++i) {
4544 MarkLive(instr, instr->OperandAt(i), &worklist);
4545 }
4546 }
4547 }
4548
4549
4550 void HGraph::MarkLive(HValue* ref, HValue* instr, ZoneList<HValue*>* worklist) {
4551 if (!instr->CheckFlag(HValue::kIsLive)) {
4552 instr->SetFlag(HValue::kIsLive);
4553 worklist->Add(instr, zone());
4554
4555 if (FLAG_trace_dead_code_elimination) {
4556 HeapStringAllocator allocator;
4557 StringStream stream(&allocator);
4558 if (ref != NULL) {
4559 ref->PrintTo(&stream);
4560 } else {
4561 stream.Add("root ");
4562 }
4563 stream.Add(" -> ");
4564 instr->PrintTo(&stream);
4565 PrintF("[MarkLive %s]\n", *stream.ToCString());
4566 }
4567 }
4568 }
4569
4570
4571 void HGraph::RemoveDeadInstructions() {
4572 ZoneList<HPhi*> dead_phis(blocks_.length(), zone());
4573
4574 // Remove any instruction not marked kIsLive.
4575 for (int i = 0; i < blocks()->length(); ++i) {
4576 HBasicBlock* block = blocks()->at(i);
4577 for (HInstruction* instr = block->first();
4578 instr != NULL;
4579 instr = instr->next()) {
4580 if (!instr->CheckFlag(HValue::kIsLive)) {
4581 // Instruction has not been marked live; assume it is dead and remove.
4582 // TODO(titzer): we don't remove constants because some special ones
4583 // might be used by later phases and are assumed to be in the graph
4584 if (!instr->IsConstant()) instr->DeleteAndReplaceWith(NULL);
4585 } else {
4586 // Clear the liveness flag to leave the graph clean for the next DCE.
4587 instr->ClearFlag(HValue::kIsLive);
4588 }
4589 }
4590 // Collect phis that are dead and remove them in the next pass.
4591 for (int j = 0; j < block->phis()->length(); j++) {
4592 HPhi* phi = block->phis()->at(j);
4593 if (!phi->CheckFlag(HValue::kIsLive)) {
4594 dead_phis.Add(phi, zone());
4595 } else {
4596 phi->ClearFlag(HValue::kIsLive);
4597 }
4598 }
4599 }
4600
4601 // Process phis separately to avoid simultaneously mutating the phi list.
4602 while (!dead_phis.is_empty()) {
4603 HPhi* phi = dead_phis.RemoveLast();
4604 HBasicBlock* block = phi->block();
4605 phi->DeleteAndReplaceWith(NULL);
4606 block->RecordDeletedPhi(phi->merged_index());
4607 }
4608 }
4609
4610
4611 void HGraph::RestoreActualValues() { 3358 void HGraph::RestoreActualValues() {
4612 HPhase phase("H_Restore actual values", this); 3359 HPhase phase("H_Restore actual values", this);
4613 3360
4614 for (int block_index = 0; block_index < blocks()->length(); block_index++) { 3361 for (int block_index = 0; block_index < blocks()->length(); block_index++) {
4615 HBasicBlock* block = blocks()->at(block_index); 3362 HBasicBlock* block = blocks()->at(block_index);
4616 3363
4617 #ifdef DEBUG 3364 #ifdef DEBUG
4618 for (int i = 0; i < block->phis()->length(); i++) { 3365 for (int i = 0; i < block->phis()->length(); i++) {
4619 HPhi* phi = block->phis()->at(i); 3366 HPhi* phi = block->phis()->at(i);
4620 ASSERT(phi->ActualValue() == phi); 3367 ASSERT(phi->ActualValue() == phi);
4621 } 3368 }
4622 #endif 3369 #endif
4623 3370
4624 for (HInstruction* instruction = block->first(); 3371 for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
4625 instruction != NULL; 3372 HInstruction* instruction = it.Current();
4626 instruction = instruction->next()) {
4627 if (instruction->ActualValue() != instruction) { 3373 if (instruction->ActualValue() != instruction) {
4628 ASSERT(instruction->IsInformativeDefinition()); 3374 ASSERT(instruction->IsInformativeDefinition());
4629 if (instruction->IsPurelyInformativeDefinition()) { 3375 if (instruction->IsPurelyInformativeDefinition()) {
4630 instruction->DeleteAndReplaceWith(instruction->RedefinedOperand()); 3376 instruction->DeleteAndReplaceWith(instruction->RedefinedOperand());
4631 } else { 3377 } else {
4632 instruction->ReplaceAllUsesWith(instruction->ActualValue()); 3378 instruction->ReplaceAllUsesWith(instruction->ActualValue());
4633 } 3379 }
4634 } 3380 }
4635 } 3381 }
4636 } 3382 }
4637 } 3383 }
4638 3384
4639 3385
4640 void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) { 3386 void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) {
4641 Push(instr); 3387 Push(instr);
4642 AddInstruction(instr); 3388 AddInstruction(instr);
4643 } 3389 }
4644 3390
4645 3391
4646 void HOptimizedGraphBuilder::AddSoftDeoptimize() {
4647 isolate()->counters()->soft_deopts_requested()->Increment();
4648 if (FLAG_always_opt) return;
4649 if (current_block()->IsDeoptimizing()) return;
4650 AddInstruction(new(zone()) HSoftDeoptimize());
4651 isolate()->counters()->soft_deopts_inserted()->Increment();
4652 current_block()->MarkAsDeoptimizing();
4653 graph()->set_has_soft_deoptimize(true);
4654 }
4655
4656
4657 template <class Instruction> 3392 template <class Instruction>
4658 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) { 3393 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) {
4659 int count = call->argument_count(); 3394 int count = call->argument_count();
4660 ZoneList<HValue*> arguments(count, zone()); 3395 ZoneList<HValue*> arguments(count, zone());
4661 for (int i = 0; i < count; ++i) { 3396 for (int i = 0; i < count; ++i) {
4662 arguments.Add(Pop(), zone()); 3397 arguments.Add(Pop(), zone());
4663 } 3398 }
4664 3399
4665 while (!arguments.is_empty()) { 3400 while (!arguments.is_empty()) {
4666 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast())); 3401 Add<HPushArgument>(arguments.RemoveLast());
4667 } 3402 }
4668 return call; 3403 return call;
4669 } 3404 }
4670 3405
4671 3406
4672 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) { 3407 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) {
4673 HConstant* undefined_constant = new(zone()) HConstant( 3408 HConstant* undefined_constant = Add<HConstant>(
4674 isolate()->factory()->undefined_value()); 3409 isolate()->factory()->undefined_value());
4675 AddInstruction(undefined_constant);
4676 graph()->set_undefined_constant(undefined_constant); 3410 graph()->set_undefined_constant(undefined_constant);
4677 3411
4678 // Create an arguments object containing the initial parameters. Set the 3412 // Create an arguments object containing the initial parameters. Set the
4679 // initial values of parameters including "this" having parameter index 0. 3413 // initial values of parameters including "this" having parameter index 0.
4680 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count()); 3414 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count());
4681 HArgumentsObject* arguments_object = 3415 HArgumentsObject* arguments_object =
4682 new(zone()) HArgumentsObject(environment()->parameter_count(), zone()); 3416 new(zone()) HArgumentsObject(environment()->parameter_count(), zone());
4683 for (int i = 0; i < environment()->parameter_count(); ++i) { 3417 for (int i = 0; i < environment()->parameter_count(); ++i) {
4684 HInstruction* parameter = AddInstruction(new(zone()) HParameter(i)); 3418 HInstruction* parameter = Add<HParameter>(i);
4685 arguments_object->AddArgument(parameter, zone()); 3419 arguments_object->AddArgument(parameter, zone());
4686 environment()->Bind(i, parameter); 3420 environment()->Bind(i, parameter);
4687 } 3421 }
4688 AddInstruction(arguments_object); 3422 AddInstruction(arguments_object);
4689 graph()->SetArgumentsObject(arguments_object); 3423 graph()->SetArgumentsObject(arguments_object);
4690 3424
4691 // First special is HContext. 3425 // First special is HContext.
4692 HInstruction* context = AddInstruction(new(zone()) HContext); 3426 HInstruction* context = Add<HContext>();
4693 environment()->BindContext(context); 3427 environment()->BindContext(context);
4694 3428
4695 // Initialize specials and locals to undefined. 3429 // Initialize specials and locals to undefined.
4696 for (int i = environment()->parameter_count() + 1; 3430 for (int i = environment()->parameter_count() + 1;
4697 i < environment()->length(); 3431 i < environment()->length();
4698 ++i) { 3432 ++i) {
4699 environment()->Bind(i, undefined_constant); 3433 environment()->Bind(i, undefined_constant);
4700 } 3434 }
4701 3435
4702 // Handle the arguments and arguments shadow variables specially (they do 3436 // Handle the arguments and arguments shadow variables specially (they do
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
4998 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); 3732 HBasicBlock* next_test_block = graph()->CreateBasicBlock();
4999 HBasicBlock* body_block = graph()->CreateBasicBlock(); 3733 HBasicBlock* body_block = graph()->CreateBasicBlock();
5000 3734
5001 HControlInstruction* compare; 3735 HControlInstruction* compare;
5002 3736
5003 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { 3737 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) {
5004 if (!clause->compare_type()->Is(Type::Smi())) { 3738 if (!clause->compare_type()->Is(Type::Smi())) {
5005 AddSoftDeoptimize(); 3739 AddSoftDeoptimize();
5006 } 3740 }
5007 3741
5008 HCompareIDAndBranch* compare_ = 3742 HCompareNumericAndBranch* compare_ =
5009 new(zone()) HCompareIDAndBranch(tag_value, 3743 new(zone()) HCompareNumericAndBranch(tag_value,
5010 label_value, 3744 label_value,
5011 Token::EQ_STRICT); 3745 Token::EQ_STRICT);
5012 compare_->set_observed_input_representation( 3746 compare_->set_observed_input_representation(
5013 Representation::Smi(), Representation::Smi()); 3747 Representation::Smi(), Representation::Smi());
5014 compare = compare_; 3748 compare = compare_;
5015 } else { 3749 } else {
5016 compare = new(zone()) HStringCompareAndBranch(context, tag_value, 3750 compare = new(zone()) HStringCompareAndBranch(context, tag_value,
5017 label_value, 3751 label_value,
5018 Token::EQ_STRICT); 3752 Token::EQ_STRICT);
5019 } 3753 }
5020 3754
5021 compare->SetSuccessorAt(0, body_block); 3755 compare->SetSuccessorAt(0, body_block);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
5095 stmt->ExitId())); 3829 stmt->ExitId()));
5096 } else { 3830 } else {
5097 if (fall_through_block != NULL) fall_through_block->Goto(break_block); 3831 if (fall_through_block != NULL) fall_through_block->Goto(break_block);
5098 if (last_block != NULL) last_block->Goto(break_block); 3832 if (last_block != NULL) last_block->Goto(break_block);
5099 break_block->SetJoinId(stmt->ExitId()); 3833 break_block->SetJoinId(stmt->ExitId());
5100 set_current_block(break_block); 3834 set_current_block(break_block);
5101 } 3835 }
5102 } 3836 }
5103 3837
5104 3838
5105 bool HOptimizedGraphBuilder::HasOsrEntryAt(IterationStatement* statement) {
5106 return statement->OsrEntryId() == current_info()->osr_ast_id();
5107 }
5108
5109
5110 bool HOptimizedGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) {
5111 if (!HasOsrEntryAt(statement)) return false;
5112
5113 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock();
5114 HBasicBlock* osr_entry = graph()->CreateBasicBlock();
5115 HValue* true_value = graph()->GetConstantTrue();
5116 HBranch* test = new(zone()) HBranch(true_value, non_osr_entry, osr_entry);
5117 current_block()->Finish(test);
5118
5119 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock();
5120 non_osr_entry->Goto(loop_predecessor);
5121
5122 set_current_block(osr_entry);
5123 osr_entry->set_osr_entry();
5124 BailoutId osr_entry_id = statement->OsrEntryId();
5125 int first_expression_index = environment()->first_expression_index();
5126 int length = environment()->length();
5127 ZoneList<HUnknownOSRValue*>* osr_values =
5128 new(zone()) ZoneList<HUnknownOSRValue*>(length, zone());
5129
5130 for (int i = 0; i < first_expression_index; ++i) {
5131 HUnknownOSRValue* osr_value = new(zone()) HUnknownOSRValue;
5132 AddInstruction(osr_value);
5133 environment()->Bind(i, osr_value);
5134 osr_values->Add(osr_value, zone());
5135 }
5136
5137 if (first_expression_index != length) {
5138 environment()->Drop(length - first_expression_index);
5139 for (int i = first_expression_index; i < length; ++i) {
5140 HUnknownOSRValue* osr_value = new(zone()) HUnknownOSRValue;
5141 AddInstruction(osr_value);
5142 environment()->Push(osr_value);
5143 osr_values->Add(osr_value, zone());
5144 }
5145 }
5146
5147 graph()->set_osr_values(osr_values);
5148
5149 AddSimulate(osr_entry_id);
5150 AddInstruction(new(zone()) HOsrEntry(osr_entry_id));
5151 HContext* context = new(zone()) HContext;
5152 AddInstruction(context);
5153 environment()->BindContext(context);
5154 current_block()->Goto(loop_predecessor);
5155 loop_predecessor->SetJoinId(statement->EntryId());
5156 set_current_block(loop_predecessor);
5157 return true;
5158 }
5159
5160
5161 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, 3839 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt,
5162 HBasicBlock* loop_entry, 3840 HBasicBlock* loop_entry,
5163 BreakAndContinueInfo* break_info) { 3841 BreakAndContinueInfo* break_info) {
5164 BreakAndContinueScope push(break_info, this); 3842 BreakAndContinueScope push(break_info, this);
5165 AddSimulate(stmt->StackCheckId()); 3843 AddSimulate(stmt->StackCheckId());
5166 HValue* context = environment()->LookupContext(); 3844 HValue* context = environment()->LookupContext();
5167 HStackCheck* stack_check = 3845 HStackCheck* stack_check = Add<HStackCheck>(
5168 new(zone()) HStackCheck(context, HStackCheck::kBackwardsBranch); 3846 context, HStackCheck::kBackwardsBranch);
5169 AddInstruction(stack_check);
5170 ASSERT(loop_entry->IsLoopHeader()); 3847 ASSERT(loop_entry->IsLoopHeader());
5171 loop_entry->loop_information()->set_stack_check(stack_check); 3848 loop_entry->loop_information()->set_stack_check(stack_check);
5172 CHECK_BAILOUT(Visit(stmt->body())); 3849 CHECK_BAILOUT(Visit(stmt->body()));
5173 } 3850 }
5174 3851
5175 3852
5176 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { 3853 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
5177 ASSERT(!HasStackOverflow()); 3854 ASSERT(!HasStackOverflow());
5178 ASSERT(current_block() != NULL); 3855 ASSERT(current_block() != NULL);
5179 ASSERT(current_block()->HasPredecessor()); 3856 ASSERT(current_block()->HasPredecessor());
5180 ASSERT(current_block() != NULL); 3857 ASSERT(current_block() != NULL);
5181 bool osr_entry = PreProcessOsrEntry(stmt); 3858 HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt);
5182 HBasicBlock* loop_entry = CreateLoopHeaderBlock();
5183 current_block()->Goto(loop_entry);
5184 set_current_block(loop_entry);
5185 if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
5186 3859
5187 BreakAndContinueInfo break_info(stmt); 3860 BreakAndContinueInfo break_info(stmt);
5188 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); 3861 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
5189 HBasicBlock* body_exit = 3862 HBasicBlock* body_exit =
5190 JoinContinue(stmt, current_block(), break_info.continue_block()); 3863 JoinContinue(stmt, current_block(), break_info.continue_block());
5191 HBasicBlock* loop_successor = NULL; 3864 HBasicBlock* loop_successor = NULL;
5192 if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) { 3865 if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) {
5193 set_current_block(body_exit); 3866 set_current_block(body_exit);
5194 // The block for a true condition, the actual predecessor block of the 3867 // The block for a true condition, the actual predecessor block of the
5195 // back edge. 3868 // back edge.
(...skipping 18 matching lines...) Expand all
5214 break_info.break_block()); 3887 break_info.break_block());
5215 set_current_block(loop_exit); 3888 set_current_block(loop_exit);
5216 } 3889 }
5217 3890
5218 3891
5219 void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { 3892 void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
5220 ASSERT(!HasStackOverflow()); 3893 ASSERT(!HasStackOverflow());
5221 ASSERT(current_block() != NULL); 3894 ASSERT(current_block() != NULL);
5222 ASSERT(current_block()->HasPredecessor()); 3895 ASSERT(current_block()->HasPredecessor());
5223 ASSERT(current_block() != NULL); 3896 ASSERT(current_block() != NULL);
5224 bool osr_entry = PreProcessOsrEntry(stmt); 3897 HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt);
5225 HBasicBlock* loop_entry = CreateLoopHeaderBlock();
5226 current_block()->Goto(loop_entry);
5227 set_current_block(loop_entry);
5228 if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
5229
5230 3898
5231 // If the condition is constant true, do not generate a branch. 3899 // If the condition is constant true, do not generate a branch.
5232 HBasicBlock* loop_successor = NULL; 3900 HBasicBlock* loop_successor = NULL;
5233 if (!stmt->cond()->ToBooleanIsTrue()) { 3901 if (!stmt->cond()->ToBooleanIsTrue()) {
5234 HBasicBlock* body_entry = graph()->CreateBasicBlock(); 3902 HBasicBlock* body_entry = graph()->CreateBasicBlock();
5235 loop_successor = graph()->CreateBasicBlock(); 3903 loop_successor = graph()->CreateBasicBlock();
5236 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); 3904 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
5237 if (body_entry->HasPredecessor()) { 3905 if (body_entry->HasPredecessor()) {
5238 body_entry->SetJoinId(stmt->BodyId()); 3906 body_entry->SetJoinId(stmt->BodyId());
5239 set_current_block(body_entry); 3907 set_current_block(body_entry);
(...skipping 21 matching lines...) Expand all
5261 3929
5262 3930
5263 void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) { 3931 void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) {
5264 ASSERT(!HasStackOverflow()); 3932 ASSERT(!HasStackOverflow());
5265 ASSERT(current_block() != NULL); 3933 ASSERT(current_block() != NULL);
5266 ASSERT(current_block()->HasPredecessor()); 3934 ASSERT(current_block()->HasPredecessor());
5267 if (stmt->init() != NULL) { 3935 if (stmt->init() != NULL) {
5268 CHECK_ALIVE(Visit(stmt->init())); 3936 CHECK_ALIVE(Visit(stmt->init()));
5269 } 3937 }
5270 ASSERT(current_block() != NULL); 3938 ASSERT(current_block() != NULL);
5271 bool osr_entry = PreProcessOsrEntry(stmt); 3939 HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt);
5272 HBasicBlock* loop_entry = CreateLoopHeaderBlock();
5273 current_block()->Goto(loop_entry);
5274 set_current_block(loop_entry);
5275 if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
5276 3940
5277 HBasicBlock* loop_successor = NULL; 3941 HBasicBlock* loop_successor = NULL;
5278 if (stmt->cond() != NULL) { 3942 if (stmt->cond() != NULL) {
5279 HBasicBlock* body_entry = graph()->CreateBasicBlock(); 3943 HBasicBlock* body_entry = graph()->CreateBasicBlock();
5280 loop_successor = graph()->CreateBasicBlock(); 3944 loop_successor = graph()->CreateBasicBlock();
5281 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); 3945 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
5282 if (body_entry->HasPredecessor()) { 3946 if (body_entry->HasPredecessor()) {
5283 body_entry->SetJoinId(stmt->BodyId()); 3947 body_entry->SetJoinId(stmt->BodyId());
5284 set_current_block(body_entry); 3948 set_current_block(body_entry);
5285 } 3949 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
5328 if (!stmt->each()->IsVariableProxy() || 3992 if (!stmt->each()->IsVariableProxy() ||
5329 !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) { 3993 !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
5330 return Bailout("ForInStatement with non-local each variable"); 3994 return Bailout("ForInStatement with non-local each variable");
5331 } 3995 }
5332 3996
5333 Variable* each_var = stmt->each()->AsVariableProxy()->var(); 3997 Variable* each_var = stmt->each()->AsVariableProxy()->var();
5334 3998
5335 CHECK_ALIVE(VisitForValue(stmt->enumerable())); 3999 CHECK_ALIVE(VisitForValue(stmt->enumerable()));
5336 HValue* enumerable = Top(); // Leave enumerable at the top. 4000 HValue* enumerable = Top(); // Leave enumerable at the top.
5337 4001
5338 HInstruction* map = AddInstruction(new(zone()) HForInPrepareMap( 4002 HInstruction* map = Add<HForInPrepareMap>(
5339 environment()->LookupContext(), enumerable)); 4003 environment()->LookupContext(), enumerable);
5340 AddSimulate(stmt->PrepareId()); 4004 AddSimulate(stmt->PrepareId());
5341 4005
5342 HInstruction* array = AddInstruction( 4006 HInstruction* array = Add<HForInCacheArray>(
5343 new(zone()) HForInCacheArray( 4007 enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex);
5344 enumerable,
5345 map,
5346 DescriptorArray::kEnumCacheBridgeCacheIndex));
5347 4008
5348 HInstruction* enum_length = AddInstruction(new(zone()) HMapEnumLength(map)); 4009 HInstruction* enum_length = Add<HMapEnumLength>(map);
5349 4010
5350 HInstruction* start_index = AddInstruction(new(zone()) HConstant(0)); 4011 HInstruction* start_index = Add<HConstant>(0);
5351 4012
5352 Push(map); 4013 Push(map);
5353 Push(array); 4014 Push(array);
5354 Push(enum_length); 4015 Push(enum_length);
5355 Push(start_index); 4016 Push(start_index);
5356 4017
5357 HInstruction* index_cache = AddInstruction( 4018 HInstruction* index_cache = Add<HForInCacheArray>(
5358 new(zone()) HForInCacheArray( 4019 enumerable, map, DescriptorArray::kEnumCacheBridgeIndicesCacheIndex);
5359 enumerable,
5360 map,
5361 DescriptorArray::kEnumCacheBridgeIndicesCacheIndex));
5362 HForInCacheArray::cast(array)->set_index_cache( 4020 HForInCacheArray::cast(array)->set_index_cache(
5363 HForInCacheArray::cast(index_cache)); 4021 HForInCacheArray::cast(index_cache));
5364 4022
5365 bool osr_entry = PreProcessOsrEntry(stmt); 4023 HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt);
5366 HBasicBlock* loop_entry = CreateLoopHeaderBlock();
5367 current_block()->Goto(loop_entry);
5368 set_current_block(loop_entry);
5369 if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
5370 4024
5371 HValue* index = environment()->ExpressionStackAt(0); 4025 HValue* index = environment()->ExpressionStackAt(0);
5372 HValue* limit = environment()->ExpressionStackAt(1); 4026 HValue* limit = environment()->ExpressionStackAt(1);
5373 4027
5374 // Check that we still have more keys. 4028 // Check that we still have more keys.
5375 HCompareIDAndBranch* compare_index = 4029 HCompareNumericAndBranch* compare_index =
5376 new(zone()) HCompareIDAndBranch(index, limit, Token::LT); 4030 new(zone()) HCompareNumericAndBranch(index, limit, Token::LT);
5377 compare_index->set_observed_input_representation( 4031 compare_index->set_observed_input_representation(
5378 Representation::Smi(), Representation::Smi()); 4032 Representation::Smi(), Representation::Smi());
5379 4033
5380 HBasicBlock* loop_body = graph()->CreateBasicBlock(); 4034 HBasicBlock* loop_body = graph()->CreateBasicBlock();
5381 HBasicBlock* loop_successor = graph()->CreateBasicBlock(); 4035 HBasicBlock* loop_successor = graph()->CreateBasicBlock();
5382 4036
5383 compare_index->SetSuccessorAt(0, loop_body); 4037 compare_index->SetSuccessorAt(0, loop_body);
5384 compare_index->SetSuccessorAt(1, loop_successor); 4038 compare_index->SetSuccessorAt(1, loop_successor);
5385 current_block()->Finish(compare_index); 4039 current_block()->Finish(compare_index);
5386 4040
5387 set_current_block(loop_successor); 4041 set_current_block(loop_successor);
5388 Drop(5); 4042 Drop(5);
5389 4043
5390 set_current_block(loop_body); 4044 set_current_block(loop_body);
5391 4045
5392 HValue* key = AddInstruction( 4046 HValue* key = Add<HLoadKeyed>(
5393 new(zone()) HLoadKeyed( 4047 environment()->ExpressionStackAt(2), // Enum cache.
5394 environment()->ExpressionStackAt(2), // Enum cache. 4048 environment()->ExpressionStackAt(0), // Iteration index.
5395 environment()->ExpressionStackAt(0), // Iteration index. 4049 environment()->ExpressionStackAt(0),
5396 environment()->ExpressionStackAt(0), 4050 FAST_ELEMENTS);
5397 FAST_ELEMENTS));
5398 4051
5399 // Check if the expected map still matches that of the enumerable. 4052 // Check if the expected map still matches that of the enumerable.
5400 // If not just deoptimize. 4053 // If not just deoptimize.
5401 AddInstruction(new(zone()) HCheckMapValue( 4054 Add<HCheckMapValue>(environment()->ExpressionStackAt(4),
5402 environment()->ExpressionStackAt(4), 4055 environment()->ExpressionStackAt(3));
5403 environment()->ExpressionStackAt(3)));
5404 4056
5405 Bind(each_var, key); 4057 Bind(each_var, key);
5406 4058
5407 BreakAndContinueInfo break_info(stmt, 5); 4059 BreakAndContinueInfo break_info(stmt, 5);
5408 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); 4060 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
5409 4061
5410 HBasicBlock* body_exit = 4062 HBasicBlock* body_exit =
5411 JoinContinue(stmt, current_block(), break_info.continue_block()); 4063 JoinContinue(stmt, current_block(), break_info.continue_block());
5412 4064
5413 if (body_exit != NULL) { 4065 if (body_exit != NULL) {
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
5566 4218
5567 return kUseCell; 4219 return kUseCell;
5568 } 4220 }
5569 4221
5570 4222
5571 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { 4223 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) {
5572 ASSERT(var->IsContextSlot()); 4224 ASSERT(var->IsContextSlot());
5573 HValue* context = environment()->LookupContext(); 4225 HValue* context = environment()->LookupContext();
5574 int length = current_info()->scope()->ContextChainLength(var->scope()); 4226 int length = current_info()->scope()->ContextChainLength(var->scope());
5575 while (length-- > 0) { 4227 while (length-- > 0) {
5576 HInstruction* context_instruction = new(zone()) HOuterContext(context); 4228 context = Add<HOuterContext>(context);
5577 AddInstruction(context_instruction);
5578 context = context_instruction;
5579 } 4229 }
5580 return context; 4230 return context;
5581 } 4231 }
5582 4232
5583 4233
5584 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) { 4234 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
5585 ASSERT(!HasStackOverflow()); 4235 ASSERT(!HasStackOverflow());
5586 ASSERT(current_block() != NULL); 4236 ASSERT(current_block() != NULL);
5587 ASSERT(current_block()->HasPredecessor()); 4237 ASSERT(current_block()->HasPredecessor());
5588 Variable* variable = expr->var(); 4238 Variable* variable = expr->var();
(...skipping 17 matching lines...) Expand all
5606 LookupGlobalProperty(variable, &lookup, false); 4256 LookupGlobalProperty(variable, &lookup, false);
5607 4257
5608 if (type == kUseCell && 4258 if (type == kUseCell &&
5609 current_info()->global_object()->IsAccessCheckNeeded()) { 4259 current_info()->global_object()->IsAccessCheckNeeded()) {
5610 type = kUseGeneric; 4260 type = kUseGeneric;
5611 } 4261 }
5612 4262
5613 if (type == kUseCell) { 4263 if (type == kUseCell) {
5614 Handle<GlobalObject> global(current_info()->global_object()); 4264 Handle<GlobalObject> global(current_info()->global_object());
5615 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); 4265 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup));
5616 HLoadGlobalCell* instr = 4266 if (cell->type()->IsConstant()) {
5617 new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails()); 4267 cell->AddDependentCompilationInfo(top_info());
5618 return ast_context()->ReturnInstruction(instr, expr->id()); 4268 Handle<Object> constant_object = cell->type()->AsConstant();
4269 if (constant_object->IsConsString()) {
4270 constant_object =
4271 FlattenGetString(Handle<String>::cast(constant_object));
4272 }
4273 HConstant* constant = new(zone()) HConstant(constant_object);
4274 return ast_context()->ReturnInstruction(constant, expr->id());
4275 } else {
4276 HLoadGlobalCell* instr =
4277 new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails());
4278 return ast_context()->ReturnInstruction(instr, expr->id());
4279 }
5619 } else { 4280 } else {
5620 HValue* context = environment()->LookupContext(); 4281 HValue* context = environment()->LookupContext();
5621 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 4282 HGlobalObject* global_object = new(zone()) HGlobalObject(context);
5622 AddInstruction(global_object); 4283 AddInstruction(global_object);
5623 HLoadGlobalGeneric* instr = 4284 HLoadGlobalGeneric* instr =
5624 new(zone()) HLoadGlobalGeneric(context, 4285 new(zone()) HLoadGlobalGeneric(context,
5625 global_object, 4286 global_object,
5626 variable->name(), 4287 variable->name(),
5627 ast_context()->is_for_typeof()); 4288 ast_context()->is_for_typeof());
5628 instr->set_position(expr->position()); 4289 instr->set_position(expr->position());
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
5861 &data_size, 4522 &data_size,
5862 &pointer_size)) { 4523 &pointer_size)) {
5863 Handle<JSObject> original_boilerplate_object = 4524 Handle<JSObject> original_boilerplate_object =
5864 Handle<JSObject>::cast(original_boilerplate); 4525 Handle<JSObject>::cast(original_boilerplate);
5865 Handle<JSObject> boilerplate_object = 4526 Handle<JSObject> boilerplate_object =
5866 DeepCopy(original_boilerplate_object); 4527 DeepCopy(original_boilerplate_object);
5867 4528
5868 literal = BuildFastLiteral(context, 4529 literal = BuildFastLiteral(context,
5869 boilerplate_object, 4530 boilerplate_object,
5870 original_boilerplate_object, 4531 original_boilerplate_object,
4532 Handle<Object>::null(),
5871 data_size, 4533 data_size,
5872 pointer_size, 4534 pointer_size,
5873 DONT_TRACK_ALLOCATION_SITE); 4535 DONT_TRACK_ALLOCATION_SITE);
5874 } else { 4536 } else {
5875 NoObservableSideEffectsScope no_effects(this); 4537 NoObservableSideEffectsScope no_effects(this);
5876 Handle<FixedArray> closure_literals(closure->literals(), isolate()); 4538 Handle<FixedArray> closure_literals(closure->literals(), isolate());
5877 Handle<FixedArray> constant_properties = expr->constant_properties(); 4539 Handle<FixedArray> constant_properties = expr->constant_properties();
5878 int literal_index = expr->literal_index(); 4540 int literal_index = expr->literal_index();
5879 int flags = expr->fast_elements() 4541 int flags = expr->fast_elements()
5880 ? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags; 4542 ? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags;
5881 flags |= expr->has_function() 4543 flags |= expr->has_function()
5882 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags; 4544 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags;
5883 4545
5884 AddInstruction(new(zone()) HPushArgument(AddInstruction( 4546 Add<HPushArgument>(Add<HConstant>(closure_literals));
5885 new(zone()) HConstant(closure_literals)))); 4547 Add<HPushArgument>(Add<HConstant>(literal_index));
5886 AddInstruction(new(zone()) HPushArgument(AddInstruction( 4548 Add<HPushArgument>(Add<HConstant>(constant_properties));
5887 new(zone()) HConstant(literal_index)))); 4549 Add<HPushArgument>(Add<HConstant>(flags));
5888 AddInstruction(new(zone()) HPushArgument(AddInstruction(
5889 new(zone()) HConstant(constant_properties))));
5890 AddInstruction(new(zone()) HPushArgument(AddInstruction(
5891 new(zone()) HConstant(flags))));
5892 4550
5893 Runtime::FunctionId function_id = 4551 Runtime::FunctionId function_id =
5894 (expr->depth() > 1 || expr->may_store_doubles()) 4552 (expr->depth() > 1 || expr->may_store_doubles())
5895 ? Runtime::kCreateObjectLiteral : Runtime::kCreateObjectLiteralShallow; 4553 ? Runtime::kCreateObjectLiteral : Runtime::kCreateObjectLiteralShallow;
5896 literal = AddInstruction( 4554 literal = Add<HCallRuntime>(context,
5897 new(zone()) HCallRuntime(context, 4555 isolate()->factory()->empty_string(),
5898 isolate()->factory()->empty_string(), 4556 Runtime::FunctionForId(function_id),
5899 Runtime::FunctionForId(function_id), 4557 4);
5900 4));
5901 } 4558 }
5902 4559
5903 // The object is expected in the bailout environment during computation 4560 // The object is expected in the bailout environment during computation
5904 // of the property values and is the value of the entire expression. 4561 // of the property values and is the value of the entire expression.
5905 Push(literal); 4562 Push(literal);
5906 4563
5907 expr->CalculateEmitStore(zone()); 4564 expr->CalculateEmitStore(zone());
5908 4565
5909 for (int i = 0; i < expr->properties()->length(); i++) { 4566 for (int i = 0; i < expr->properties()->length(); i++) {
5910 ObjectLiteral::Property* property = expr->properties()->at(i); 4567 ObjectLiteral::Property* property = expr->properties()->at(i);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
5956 default: UNREACHABLE(); 4613 default: UNREACHABLE();
5957 } 4614 }
5958 } 4615 }
5959 4616
5960 if (expr->has_function()) { 4617 if (expr->has_function()) {
5961 // Return the result of the transformation to fast properties 4618 // Return the result of the transformation to fast properties
5962 // instead of the original since this operation changes the map 4619 // instead of the original since this operation changes the map
5963 // of the object. This makes sure that the original object won't 4620 // of the object. This makes sure that the original object won't
5964 // be used by other optimized code before it is transformed 4621 // be used by other optimized code before it is transformed
5965 // (e.g. because of code motion). 4622 // (e.g. because of code motion).
5966 HToFastProperties* result = new(zone()) HToFastProperties(Pop()); 4623 HToFastProperties* result = Add<HToFastProperties>(Pop());
5967 AddInstruction(result);
5968 return ast_context()->ReturnValue(result); 4624 return ast_context()->ReturnValue(result);
5969 } else { 4625 } else {
5970 return ast_context()->ReturnValue(Pop()); 4626 return ast_context()->ReturnValue(Pop());
5971 } 4627 }
5972 } 4628 }
5973 4629
5974 4630
5975 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { 4631 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
5976 ASSERT(!HasStackOverflow()); 4632 ASSERT(!HasStackOverflow());
5977 ASSERT(current_block() != NULL); 4633 ASSERT(current_block() != NULL);
5978 ASSERT(current_block()->HasPredecessor()); 4634 ASSERT(current_block()->HasPredecessor());
5979 ZoneList<Expression*>* subexprs = expr->values(); 4635 ZoneList<Expression*>* subexprs = expr->values();
5980 int length = subexprs->length(); 4636 int length = subexprs->length();
5981 HValue* context = environment()->LookupContext(); 4637 HValue* context = environment()->LookupContext();
5982 HInstruction* literal; 4638 HInstruction* literal;
5983 4639
4640 Handle<AllocationSite> site;
5984 Handle<FixedArray> literals(environment()->closure()->literals(), isolate()); 4641 Handle<FixedArray> literals(environment()->closure()->literals(), isolate());
5985 Handle<Object> raw_boilerplate(literals->get(expr->literal_index()), 4642 bool uninitialized = false;
5986 isolate()); 4643 Handle<Object> literals_cell(literals->get(expr->literal_index()),
5987 4644 isolate());
5988 if (raw_boilerplate->IsUndefined()) { 4645 Handle<Object> raw_boilerplate;
4646 if (literals_cell->IsUndefined()) {
4647 uninitialized = true;
5989 raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate( 4648 raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate(
5990 isolate(), literals, expr->constant_elements()); 4649 isolate(), literals, expr->constant_elements());
5991 if (raw_boilerplate.is_null()) { 4650 if (raw_boilerplate.is_null()) {
5992 return Bailout("array boilerplate creation failed"); 4651 return Bailout("array boilerplate creation failed");
5993 } 4652 }
5994 literals->set(expr->literal_index(), *raw_boilerplate); 4653
4654 site = isolate()->factory()->NewAllocationSite();
4655 site->set_payload(*raw_boilerplate);
4656 literals->set(expr->literal_index(), *site);
4657
5995 if (JSObject::cast(*raw_boilerplate)->elements()->map() == 4658 if (JSObject::cast(*raw_boilerplate)->elements()->map() ==
5996 isolate()->heap()->fixed_cow_array_map()) { 4659 isolate()->heap()->fixed_cow_array_map()) {
5997 isolate()->counters()->cow_arrays_created_runtime()->Increment(); 4660 isolate()->counters()->cow_arrays_created_runtime()->Increment();
5998 } 4661 }
4662 } else {
4663 ASSERT(literals_cell->IsAllocationSite());
4664 site = Handle<AllocationSite>::cast(literals_cell);
4665 raw_boilerplate = Handle<Object>(site->payload(), isolate());
5999 } 4666 }
6000 4667
4668 ASSERT(!raw_boilerplate.is_null());
4669 ASSERT(site->IsLiteralSite());
4670
6001 Handle<JSObject> original_boilerplate_object = 4671 Handle<JSObject> original_boilerplate_object =
6002 Handle<JSObject>::cast(raw_boilerplate); 4672 Handle<JSObject>::cast(raw_boilerplate);
6003 ElementsKind boilerplate_elements_kind = 4673 ElementsKind boilerplate_elements_kind =
6004 Handle<JSObject>::cast(original_boilerplate_object)->GetElementsKind(); 4674 Handle<JSObject>::cast(original_boilerplate_object)->GetElementsKind();
6005 4675
6006 // TODO(mvstanton): This heuristic is only a temporary solution. In the 4676 // TODO(mvstanton): This heuristic is only a temporary solution. In the
6007 // end, we want to quit creating allocation site info after a certain number 4677 // end, we want to quit creating allocation site info after a certain number
6008 // of GCs for a call site. 4678 // of GCs for a call site.
6009 AllocationSiteMode mode = AllocationSiteInfo::GetMode( 4679 AllocationSiteMode mode = AllocationSite::GetMode(
6010 boilerplate_elements_kind); 4680 boilerplate_elements_kind);
6011 4681
6012 // Check whether to use fast or slow deep-copying for boilerplate. 4682 // Check whether to use fast or slow deep-copying for boilerplate.
6013 int data_size = 0; 4683 int data_size = 0;
6014 int pointer_size = 0; 4684 int pointer_size = 0;
6015 int max_properties = kMaxFastLiteralProperties; 4685 int max_properties = kMaxFastLiteralProperties;
6016 if (IsFastLiteral(original_boilerplate_object, 4686 if (IsFastLiteral(original_boilerplate_object,
6017 kMaxFastLiteralDepth, 4687 kMaxFastLiteralDepth,
6018 &max_properties, 4688 &max_properties,
6019 &data_size, 4689 &data_size,
6020 &pointer_size)) { 4690 &pointer_size)) {
6021 if (mode == TRACK_ALLOCATION_SITE) { 4691 if (mode == TRACK_ALLOCATION_SITE) {
6022 pointer_size += AllocationSiteInfo::kSize; 4692 pointer_size += AllocationSiteInfo::kSize;
6023 } 4693 }
6024 4694
6025 Handle<JSObject> boilerplate_object = DeepCopy(original_boilerplate_object); 4695 Handle<JSObject> boilerplate_object = DeepCopy(original_boilerplate_object);
6026 literal = BuildFastLiteral(context, 4696 literal = BuildFastLiteral(context,
6027 boilerplate_object, 4697 boilerplate_object,
6028 original_boilerplate_object, 4698 original_boilerplate_object,
4699 site,
6029 data_size, 4700 data_size,
6030 pointer_size, 4701 pointer_size,
6031 mode); 4702 mode);
6032 } else { 4703 } else {
6033 NoObservableSideEffectsScope no_effects(this); 4704 NoObservableSideEffectsScope no_effects(this);
6034 // Boilerplate already exists and constant elements are never accessed, 4705 // Boilerplate already exists and constant elements are never accessed,
6035 // pass an empty fixed array to the runtime function instead. 4706 // pass an empty fixed array to the runtime function instead.
6036 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); 4707 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array();
6037 int literal_index = expr->literal_index(); 4708 int literal_index = expr->literal_index();
6038 4709
6039 AddInstruction(new(zone()) HPushArgument(AddInstruction( 4710 Add<HPushArgument>(Add<HConstant>(literals));
6040 new(zone()) HConstant(literals)))); 4711 Add<HPushArgument>(Add<HConstant>(literal_index));
6041 AddInstruction(new(zone()) HPushArgument(AddInstruction( 4712 Add<HPushArgument>(Add<HConstant>(constants));
6042 new(zone()) HConstant(literal_index))));
6043 AddInstruction(new(zone()) HPushArgument(AddInstruction(
6044 new(zone()) HConstant(constants))));
6045 4713
6046 Runtime::FunctionId function_id = (expr->depth() > 1) 4714 Runtime::FunctionId function_id = (expr->depth() > 1)
6047 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; 4715 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow;
6048 literal = AddInstruction( 4716 literal = Add<HCallRuntime>(context,
6049 new(zone()) HCallRuntime(context, 4717 isolate()->factory()->empty_string(),
6050 isolate()->factory()->empty_string(), 4718 Runtime::FunctionForId(function_id),
6051 Runtime::FunctionForId(function_id), 4719 3);
6052 3));
6053 4720
6054 // De-opt if elements kind changed from boilerplate_elements_kind. 4721 // De-opt if elements kind changed from boilerplate_elements_kind.
6055 Handle<Map> map = Handle<Map>(original_boilerplate_object->map(), 4722 Handle<Map> map = Handle<Map>(original_boilerplate_object->map(),
6056 isolate()); 4723 isolate());
6057 AddInstruction(HCheckMaps::New(literal, map, zone())); 4724 AddInstruction(HCheckMaps::New(literal, map, zone()));
6058 } 4725 }
6059 4726
6060 // The array is expected in the bailout environment during computation 4727 // The array is expected in the bailout environment during computation
6061 // of the property values and is the value of the entire expression. 4728 // of the property values and is the value of the entire expression.
6062 Push(literal); 4729 Push(literal);
6063 // The literal index is on the stack, too. 4730 // The literal index is on the stack, too.
6064 Push(AddInstruction(new(zone()) HConstant(expr->literal_index()))); 4731 Push(Add<HConstant>(expr->literal_index()));
6065 4732
6066 HInstruction* elements = NULL; 4733 HInstruction* elements = NULL;
6067 4734
6068 for (int i = 0; i < length; i++) { 4735 for (int i = 0; i < length; i++) {
6069 Expression* subexpr = subexprs->at(i); 4736 Expression* subexpr = subexprs->at(i);
6070 // If the subexpression is a literal or a simple materialized literal it 4737 // If the subexpression is a literal or a simple materialized literal it
6071 // is already set in the cloned array. 4738 // is already set in the cloned array.
6072 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 4739 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
6073 4740
6074 CHECK_ALIVE(VisitForValue(subexpr)); 4741 CHECK_ALIVE(VisitForValue(subexpr));
6075 HValue* value = Pop(); 4742 HValue* value = Pop();
6076 if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal"); 4743 if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal");
6077 4744
6078 elements = AddLoadElements(literal); 4745 elements = AddLoadElements(literal);
6079 4746
6080 HValue* key = AddInstruction(new(zone()) HConstant(i)); 4747 HValue* key = Add<HConstant>(i);
6081 4748
6082 switch (boilerplate_elements_kind) { 4749 switch (boilerplate_elements_kind) {
6083 case FAST_SMI_ELEMENTS: 4750 case FAST_SMI_ELEMENTS:
6084 case FAST_HOLEY_SMI_ELEMENTS: 4751 case FAST_HOLEY_SMI_ELEMENTS:
6085 case FAST_ELEMENTS: 4752 case FAST_ELEMENTS:
6086 case FAST_HOLEY_ELEMENTS: 4753 case FAST_HOLEY_ELEMENTS:
6087 case FAST_DOUBLE_ELEMENTS: 4754 case FAST_DOUBLE_ELEMENTS:
6088 case FAST_HOLEY_DOUBLE_ELEMENTS: 4755 case FAST_HOLEY_DOUBLE_ELEMENTS: {
6089 AddInstruction(new(zone()) HStoreKeyed( 4756 HStoreKeyed* instr = Add<HStoreKeyed>(elements, key, value,
6090 elements, 4757 boilerplate_elements_kind);
6091 key, 4758 instr->SetUninitialized(uninitialized);
6092 value,
6093 boilerplate_elements_kind));
6094 break; 4759 break;
4760 }
6095 default: 4761 default:
6096 UNREACHABLE(); 4762 UNREACHABLE();
6097 break; 4763 break;
6098 } 4764 }
6099 4765
6100 AddSimulate(expr->GetIdForElement(i)); 4766 AddSimulate(expr->GetIdForElement(i));
6101 } 4767 }
6102 4768
6103 Drop(1); // array literal index 4769 Drop(1); // array literal index
6104 return ast_context()->ReturnValue(Pop()); 4770 return ast_context()->ReturnValue(Pop());
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
6180 // We only need to check up to the preexisting property. 4846 // We only need to check up to the preexisting property.
6181 proto = proto_result.holder(); 4847 proto = proto_result.holder();
6182 } else { 4848 } else {
6183 // Otherwise, find the top prototype. 4849 // Otherwise, find the top prototype.
6184 while (proto->GetPrototype(isolate())->IsJSObject()) { 4850 while (proto->GetPrototype(isolate())->IsJSObject()) {
6185 proto = proto->GetPrototype(isolate()); 4851 proto = proto->GetPrototype(isolate());
6186 } 4852 }
6187 ASSERT(proto->GetPrototype(isolate())->IsNull()); 4853 ASSERT(proto->GetPrototype(isolate())->IsNull());
6188 } 4854 }
6189 ASSERT(proto->IsJSObject()); 4855 ASSERT(proto->IsJSObject());
6190 AddInstruction(new(zone()) HCheckPrototypeMaps( 4856 Add<HCheckPrototypeMaps>(Handle<JSObject>(JSObject::cast(map->prototype())),
6191 Handle<JSObject>(JSObject::cast(map->prototype())), 4857 Handle<JSObject>(JSObject::cast(proto)),
6192 Handle<JSObject>(JSObject::cast(proto)), 4858 zone(), top_info());
6193 zone(),
6194 top_info()));
6195 } 4859 }
6196 4860
6197 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name); 4861 HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name);
6198 Representation representation = ComputeLoadStoreRepresentation(map, lookup); 4862 Representation representation = ComputeLoadStoreRepresentation(map, lookup);
6199 bool transition_to_field = lookup->IsTransitionToField(*map); 4863 bool transition_to_field = lookup->IsTransitionToField(*map);
6200 4864
6201 HStoreNamedField *instr; 4865 HStoreNamedField *instr;
6202 if (FLAG_track_double_fields && representation.IsDouble()) { 4866 if (FLAG_track_double_fields && representation.IsDouble()) {
6203 if (transition_to_field) { 4867 if (transition_to_field) {
6204 // The store requires a mutable HeapNumber to be allocated. 4868 // The store requires a mutable HeapNumber to be allocated.
6205 NoObservableSideEffectsScope no_side_effects(this); 4869 NoObservableSideEffectsScope no_side_effects(this);
6206 HInstruction* heap_number_size = AddInstruction(new(zone()) HConstant( 4870 HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize);
6207 HeapNumber::kSize)); 4871 HInstruction* double_box = Add<HAllocate>(
6208 HInstruction* double_box = AddInstruction(new(zone()) HAllocate(
6209 environment()->LookupContext(), heap_number_size, 4872 environment()->LookupContext(), heap_number_size,
6210 HType::HeapNumber(), HAllocate::CAN_ALLOCATE_IN_NEW_SPACE)); 4873 HType::HeapNumber(), HAllocate::CAN_ALLOCATE_IN_NEW_SPACE);
6211 AddStoreMapConstant(double_box, isolate()->factory()->heap_number_map()); 4874 AddStoreMapConstant(double_box, isolate()->factory()->heap_number_map());
6212 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), 4875 AddStore(double_box, HObjectAccess::ForHeapNumberValue(),
6213 value, Representation::Double()); 4876 value, Representation::Double());
6214 instr = new(zone()) HStoreNamedField(object, field_access, double_box); 4877 instr = new(zone()) HStoreNamedField(object, field_access, double_box);
6215 } else { 4878 } else {
6216 // Already holds a HeapNumber; load the box and write its value field. 4879 // Already holds a HeapNumber; load the box and write its value field.
6217 HInstruction* double_box = AddLoad(object, field_access); 4880 HInstruction* double_box = AddLoad(object, field_access);
6218 double_box->set_type(HType::HeapNumber()); 4881 double_box->set_type(HType::HeapNumber());
6219 instr = new(zone()) HStoreNamedField(double_box, 4882 instr = new(zone()) HStoreNamedField(double_box,
6220 HObjectAccess::ForHeapNumberValue(), value, Representation::Double()); 4883 HObjectAccess::ForHeapNumberValue(), value, Representation::Double());
(...skipping 29 matching lines...) Expand all
6250 } 4913 }
6251 4914
6252 4915
6253 HInstruction* HOptimizedGraphBuilder::BuildCallSetter( 4916 HInstruction* HOptimizedGraphBuilder::BuildCallSetter(
6254 HValue* object, 4917 HValue* object,
6255 HValue* value, 4918 HValue* value,
6256 Handle<Map> map, 4919 Handle<Map> map,
6257 Handle<JSFunction> setter, 4920 Handle<JSFunction> setter,
6258 Handle<JSObject> holder) { 4921 Handle<JSObject> holder) {
6259 AddCheckConstantFunction(holder, object, map); 4922 AddCheckConstantFunction(holder, object, map);
6260 AddInstruction(new(zone()) HPushArgument(object)); 4923 Add<HPushArgument>(object);
6261 AddInstruction(new(zone()) HPushArgument(value)); 4924 Add<HPushArgument>(value);
6262 return new(zone()) HCallConstantFunction(setter, 2); 4925 return new(zone()) HCallConstantFunction(setter, 2);
6263 } 4926 }
6264 4927
6265 4928
6266 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic( 4929 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic(
6267 HValue* object, 4930 HValue* object,
6268 Handle<String> name, 4931 Handle<String> name,
6269 HValue* value, 4932 HValue* value,
6270 Handle<Map> map) { 4933 Handle<Map> map) {
6271 // Handle a store to a known field. 4934 // Handle a store to a known field.
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
6430 LookupResult lookup(isolate()); 5093 LookupResult lookup(isolate());
6431 if (ComputeLoadStoreField(map, name, &lookup, true)) { 5094 if (ComputeLoadStoreField(map, name, &lookup, true)) {
6432 if (count == 0) { 5095 if (count == 0) {
6433 BuildCheckHeapObject(object); 5096 BuildCheckHeapObject(object);
6434 join = graph()->CreateBasicBlock(); 5097 join = graph()->CreateBasicBlock();
6435 } 5098 }
6436 ++count; 5099 ++count;
6437 HBasicBlock* if_true = graph()->CreateBasicBlock(); 5100 HBasicBlock* if_true = graph()->CreateBasicBlock();
6438 HBasicBlock* if_false = graph()->CreateBasicBlock(); 5101 HBasicBlock* if_false = graph()->CreateBasicBlock();
6439 HCompareMap* compare = 5102 HCompareMap* compare =
6440 new(zone()) HCompareMap(object, map, if_true, if_false); 5103 new(zone()) HCompareMap(object, map, if_true, if_false);
6441 current_block()->Finish(compare); 5104 current_block()->Finish(compare);
6442 5105
6443 set_current_block(if_true); 5106 set_current_block(if_true);
6444 HInstruction* instr; 5107 HInstruction* instr;
6445 CHECK_ALIVE( 5108 CHECK_ALIVE(
6446 instr = BuildStoreNamedField(object, name, value, map, &lookup)); 5109 instr = BuildStoreNamedField(object, name, value, map, &lookup));
6447 instr->set_position(position); 5110 instr->set_position(position);
6448 // Goto will add the HSimulate for the store. 5111 // Goto will add the HSimulate for the store.
6449 AddInstruction(instr); 5112 AddInstruction(instr);
6450 if (!ast_context()->IsEffect()) Push(value); 5113 if (!ast_context()->IsEffect()) Push(value);
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
6531 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( 5194 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
6532 Variable* var, 5195 Variable* var,
6533 HValue* value, 5196 HValue* value,
6534 int position, 5197 int position,
6535 BailoutId ast_id) { 5198 BailoutId ast_id) {
6536 LookupResult lookup(isolate()); 5199 LookupResult lookup(isolate());
6537 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); 5200 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true);
6538 if (type == kUseCell) { 5201 if (type == kUseCell) {
6539 Handle<GlobalObject> global(current_info()->global_object()); 5202 Handle<GlobalObject> global(current_info()->global_object());
6540 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); 5203 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup));
5204 if (cell->type()->IsConstant()) {
5205 IfBuilder builder(this);
5206 HValue* constant = Add<HConstant>(cell->type()->AsConstant());
5207 if (cell->type()->AsConstant()->IsNumber()) {
5208 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ);
5209 } else {
5210 builder.If<HCompareObjectEqAndBranch>(value, constant);
5211 }
5212 builder.Then();
5213 builder.Else();
5214 AddSoftDeoptimize(MUST_EMIT_SOFT_DEOPT);
5215 builder.End();
5216 }
6541 HInstruction* instr = 5217 HInstruction* instr =
6542 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); 5218 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails());
6543 instr->set_position(position); 5219 instr->set_position(position);
6544 AddInstruction(instr);
6545 if (instr->HasObservableSideEffects()) { 5220 if (instr->HasObservableSideEffects()) {
6546 AddSimulate(ast_id, REMOVABLE_SIMULATE); 5221 AddSimulate(ast_id, REMOVABLE_SIMULATE);
6547 } 5222 }
6548 } else { 5223 } else {
6549 HValue* context = environment()->LookupContext(); 5224 HValue* context = environment()->LookupContext();
6550 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 5225 HGlobalObject* global_object = Add<HGlobalObject>(context);
6551 AddInstruction(global_object);
6552 HStoreGlobalGeneric* instr = 5226 HStoreGlobalGeneric* instr =
6553 new(zone()) HStoreGlobalGeneric(context, 5227 Add<HStoreGlobalGeneric>(context, global_object, var->name(),
6554 global_object, 5228 value, function_strict_mode_flag());
6555 var->name(),
6556 value,
6557 function_strict_mode_flag());
6558 instr->set_position(position); 5229 instr->set_position(position);
6559 AddInstruction(instr);
6560 ASSERT(instr->HasObservableSideEffects()); 5230 ASSERT(instr->HasObservableSideEffects());
6561 AddSimulate(ast_id, REMOVABLE_SIMULATE); 5231 AddSimulate(ast_id, REMOVABLE_SIMULATE);
6562 } 5232 }
6563 } 5233 }
6564 5234
6565 5235
6566 void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr, 5236 void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr,
6567 BailoutId id, 5237 BailoutId id,
6568 int position, 5238 int position,
6569 BailoutId assignment_id, 5239 BailoutId assignment_id,
(...skipping 15 matching lines...) Expand all
6585 if (monomorphic) { 5255 if (monomorphic) {
6586 Handle<JSFunction> setter; 5256 Handle<JSFunction> setter;
6587 Handle<JSObject> holder; 5257 Handle<JSObject> holder;
6588 if (LookupSetter(map, name, &setter, &holder)) { 5258 if (LookupSetter(map, name, &setter, &holder)) {
6589 AddCheckConstantFunction(holder, object, map); 5259 AddCheckConstantFunction(holder, object, map);
6590 if (FLAG_inline_accessors && 5260 if (FLAG_inline_accessors &&
6591 TryInlineSetter(setter, id, assignment_id, value)) { 5261 TryInlineSetter(setter, id, assignment_id, value)) {
6592 return; 5262 return;
6593 } 5263 }
6594 Drop(2); 5264 Drop(2);
6595 AddInstruction(new(zone()) HPushArgument(object)); 5265 Add<HPushArgument>(object);
6596 AddInstruction(new(zone()) HPushArgument(value)); 5266 Add<HPushArgument>(value);
6597 instr = new(zone()) HCallConstantFunction(setter, 2); 5267 instr = new(zone()) HCallConstantFunction(setter, 2);
6598 } else { 5268 } else {
6599 Drop(2); 5269 Drop(2);
6600 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, 5270 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object,
6601 name, 5271 name,
6602 value, 5272 value,
6603 map)); 5273 map));
6604 } 5274 }
6605 5275
6606 } else if (types != NULL && types->length() > 1) { 5276 } else if (types != NULL && types->length() > 1) {
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
6683 return ast_context()->ReturnValue(Pop()); 5353 return ast_context()->ReturnValue(Pop());
6684 case CONST_HARMONY: 5354 case CONST_HARMONY:
6685 // This case is checked statically so no need to 5355 // This case is checked statically so no need to
6686 // perform checks here 5356 // perform checks here
6687 UNREACHABLE(); 5357 UNREACHABLE();
6688 default: 5358 default:
6689 mode = HStoreContextSlot::kNoCheck; 5359 mode = HStoreContextSlot::kNoCheck;
6690 } 5360 }
6691 5361
6692 HValue* context = BuildContextChainWalk(var); 5362 HValue* context = BuildContextChainWalk(var);
6693 HStoreContextSlot* instr = 5363 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(),
6694 new(zone()) HStoreContextSlot(context, var->index(), mode, Top()); 5364 mode, Top());
6695 AddInstruction(instr);
6696 if (instr->HasObservableSideEffects()) { 5365 if (instr->HasObservableSideEffects()) {
6697 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); 5366 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE);
6698 } 5367 }
6699 break; 5368 break;
6700 } 5369 }
6701 5370
6702 case Variable::LOOKUP: 5371 case Variable::LOOKUP:
6703 return Bailout("compound assignment to lookup slot"); 5372 return Bailout("compound assignment to lookup slot");
6704 } 5373 }
6705 return ast_context()->ReturnValue(Pop()); 5374 return ast_context()->ReturnValue(Pop());
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
6815 if (var->mode() == CONST) { 5484 if (var->mode() == CONST) {
6816 if (expr->op() != Token::INIT_CONST) { 5485 if (expr->op() != Token::INIT_CONST) {
6817 CHECK_ALIVE(VisitForValue(expr->value())); 5486 CHECK_ALIVE(VisitForValue(expr->value()));
6818 return ast_context()->ReturnValue(Pop()); 5487 return ast_context()->ReturnValue(Pop());
6819 } 5488 }
6820 5489
6821 if (var->IsStackAllocated()) { 5490 if (var->IsStackAllocated()) {
6822 // We insert a use of the old value to detect unsupported uses of const 5491 // We insert a use of the old value to detect unsupported uses of const
6823 // variables (e.g. initialization inside a loop). 5492 // variables (e.g. initialization inside a loop).
6824 HValue* old_value = environment()->Lookup(var); 5493 HValue* old_value = environment()->Lookup(var);
6825 AddInstruction(new(zone()) HUseConst(old_value)); 5494 Add<HUseConst>(old_value);
6826 } 5495 }
6827 } else if (var->mode() == CONST_HARMONY) { 5496 } else if (var->mode() == CONST_HARMONY) {
6828 if (expr->op() != Token::INIT_CONST_HARMONY) { 5497 if (expr->op() != Token::INIT_CONST_HARMONY) {
6829 return Bailout("non-initializer assignment to const"); 5498 return Bailout("non-initializer assignment to const");
6830 } 5499 }
6831 } 5500 }
6832 5501
6833 if (proxy->IsArguments()) return Bailout("assignment to arguments"); 5502 if (proxy->IsArguments()) return Bailout("assignment to arguments");
6834 5503
6835 // Handle the assignment. 5504 // Handle the assignment.
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
6896 expr->op() == Token::INIT_LET || 5565 expr->op() == Token::INIT_LET ||
6897 expr->op() == Token::INIT_CONST_HARMONY) { 5566 expr->op() == Token::INIT_CONST_HARMONY) {
6898 mode = HStoreContextSlot::kNoCheck; 5567 mode = HStoreContextSlot::kNoCheck;
6899 } else { 5568 } else {
6900 ASSERT(expr->op() == Token::INIT_CONST); 5569 ASSERT(expr->op() == Token::INIT_CONST);
6901 5570
6902 mode = HStoreContextSlot::kCheckIgnoreAssignment; 5571 mode = HStoreContextSlot::kCheckIgnoreAssignment;
6903 } 5572 }
6904 5573
6905 HValue* context = BuildContextChainWalk(var); 5574 HValue* context = BuildContextChainWalk(var);
6906 HStoreContextSlot* instr = new(zone()) HStoreContextSlot( 5575 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(),
6907 context, var->index(), mode, Top()); 5576 mode, Top());
6908 AddInstruction(instr);
6909 if (instr->HasObservableSideEffects()) { 5577 if (instr->HasObservableSideEffects()) {
6910 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); 5578 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE);
6911 } 5579 }
6912 return ast_context()->ReturnValue(Pop()); 5580 return ast_context()->ReturnValue(Pop());
6913 } 5581 }
6914 5582
6915 case Variable::LOOKUP: 5583 case Variable::LOOKUP:
6916 return Bailout("assignment to LOOKUP variable"); 5584 return Bailout("assignment to LOOKUP variable");
6917 } 5585 }
6918 } else { 5586 } else {
(...skipping 13 matching lines...) Expand all
6932 ASSERT(current_block() != NULL); 5600 ASSERT(current_block() != NULL);
6933 ASSERT(current_block()->HasPredecessor()); 5601 ASSERT(current_block()->HasPredecessor());
6934 // We don't optimize functions with invalid left-hand sides in 5602 // We don't optimize functions with invalid left-hand sides in
6935 // assignments, count operations, or for-in. Consequently throw can 5603 // assignments, count operations, or for-in. Consequently throw can
6936 // currently only occur in an effect context. 5604 // currently only occur in an effect context.
6937 ASSERT(ast_context()->IsEffect()); 5605 ASSERT(ast_context()->IsEffect());
6938 CHECK_ALIVE(VisitForValue(expr->exception())); 5606 CHECK_ALIVE(VisitForValue(expr->exception()));
6939 5607
6940 HValue* context = environment()->LookupContext(); 5608 HValue* context = environment()->LookupContext();
6941 HValue* value = environment()->Pop(); 5609 HValue* value = environment()->Pop();
6942 HThrow* instr = new(zone()) HThrow(context, value); 5610 HThrow* instr = Add<HThrow>(context, value);
6943 instr->set_position(expr->position()); 5611 instr->set_position(expr->position());
6944 AddInstruction(instr);
6945 AddSimulate(expr->id()); 5612 AddSimulate(expr->id());
6946 current_block()->FinishExit(new(zone()) HAbnormalExit); 5613 current_block()->FinishExit(new(zone()) HAbnormalExit);
6947 set_current_block(NULL); 5614 set_current_block(NULL);
6948 } 5615 }
6949 5616
6950 5617
6951 HLoadNamedField* HGraphBuilder::BuildLoadNamedField( 5618 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(
6952 HValue* object, 5619 HValue* object,
6953 HObjectAccess access, 5620 HObjectAccess access,
6954 Representation representation) { 5621 Representation representation) {
(...skipping 25 matching lines...) Expand all
6980 return new(zone()) HLoadNamedGeneric(context, object, name); 5647 return new(zone()) HLoadNamedGeneric(context, object, name);
6981 } 5648 }
6982 5649
6983 5650
6984 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( 5651 HInstruction* HOptimizedGraphBuilder::BuildCallGetter(
6985 HValue* object, 5652 HValue* object,
6986 Handle<Map> map, 5653 Handle<Map> map,
6987 Handle<JSFunction> getter, 5654 Handle<JSFunction> getter,
6988 Handle<JSObject> holder) { 5655 Handle<JSObject> holder) {
6989 AddCheckConstantFunction(holder, object, map); 5656 AddCheckConstantFunction(holder, object, map);
6990 AddInstruction(new(zone()) HPushArgument(object)); 5657 Add<HPushArgument>(object);
6991 return new(zone()) HCallConstantFunction(getter, 1); 5658 return new(zone()) HCallConstantFunction(getter, 1);
6992 } 5659 }
6993 5660
6994 5661
6995 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic( 5662 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
6996 HValue* object, 5663 HValue* object,
6997 Handle<String> name, 5664 Handle<String> name,
6998 Property* expr, 5665 Property* expr,
6999 Handle<Map> map) { 5666 Handle<Map> map) {
7000 // Handle a load from a known field. 5667 // Handle a load from a known field.
(...skipping 24 matching lines...) Expand all
7025 return new(zone()) HConstant(function); 5692 return new(zone()) HConstant(function);
7026 } 5693 }
7027 5694
7028 // Handle a load from a known field somewhere in the prototype chain. 5695 // Handle a load from a known field somewhere in the prototype chain.
7029 LookupInPrototypes(map, name, &lookup); 5696 LookupInPrototypes(map, name, &lookup);
7030 if (lookup.IsField()) { 5697 if (lookup.IsField()) {
7031 Handle<JSObject> prototype(JSObject::cast(map->prototype())); 5698 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
7032 Handle<JSObject> holder(lookup.holder()); 5699 Handle<JSObject> holder(lookup.holder());
7033 Handle<Map> holder_map(holder->map()); 5700 Handle<Map> holder_map(holder->map());
7034 AddCheckMap(object, map); 5701 AddCheckMap(object, map);
7035 AddInstruction(new(zone()) HCheckPrototypeMaps( 5702 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info());
7036 prototype, holder, zone(), top_info())); 5703 HValue* holder_value = Add<HConstant>(holder);
7037 HValue* holder_value = AddInstruction(new(zone()) HConstant(holder));
7038 return BuildLoadNamedField(holder_value, 5704 return BuildLoadNamedField(holder_value,
7039 HObjectAccess::ForField(holder_map, &lookup, name), 5705 HObjectAccess::ForField(holder_map, &lookup, name),
7040 ComputeLoadStoreRepresentation(map, &lookup)); 5706 ComputeLoadStoreRepresentation(map, &lookup));
7041 } 5707 }
7042 5708
7043 // Handle a load of a constant function somewhere in the prototype chain. 5709 // Handle a load of a constant function somewhere in the prototype chain.
7044 if (lookup.IsConstantFunction()) { 5710 if (lookup.IsConstantFunction()) {
7045 Handle<JSObject> prototype(JSObject::cast(map->prototype())); 5711 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
7046 Handle<JSObject> holder(lookup.holder()); 5712 Handle<JSObject> holder(lookup.holder());
7047 Handle<Map> holder_map(holder->map()); 5713 Handle<Map> holder_map(holder->map());
7048 AddCheckMap(object, map); 5714 AddCheckMap(object, map);
7049 AddInstruction(new(zone()) HCheckPrototypeMaps( 5715 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info());
7050 prototype, holder, zone(), top_info()));
7051 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map)); 5716 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map));
7052 return new(zone()) HConstant(function); 5717 return new(zone()) HConstant(function);
7053 } 5718 }
7054 5719
7055 // No luck, do a generic load. 5720 // No luck, do a generic load.
7056 return BuildLoadNamedGeneric(object, name, expr); 5721 return BuildLoadNamedGeneric(object, name, expr);
7057 } 5722 }
7058 5723
7059 5724
7060 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, 5725 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
(...skipping 16 matching lines...) Expand all
7077 if (dependency) { 5742 if (dependency) {
7078 mapcheck->ClearGVNFlag(kDependsOnElementsKind); 5743 mapcheck->ClearGVNFlag(kDependsOnElementsKind);
7079 } 5744 }
7080 5745
7081 // Loads from a "stock" fast holey double arrays can elide the hole check. 5746 // Loads from a "stock" fast holey double arrays can elide the hole check.
7082 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; 5747 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
7083 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) && 5748 if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) &&
7084 isolate()->IsFastArrayConstructorPrototypeChainIntact()) { 5749 isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
7085 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate()); 5750 Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate());
7086 Handle<JSObject> object_prototype = isolate()->initial_object_prototype(); 5751 Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
7087 AddInstruction(new(zone()) HCheckPrototypeMaps( 5752 Add<HCheckPrototypeMaps>(prototype, object_prototype, zone(), top_info());
7088 prototype, object_prototype, zone(), top_info()));
7089 load_mode = ALLOW_RETURN_HOLE; 5753 load_mode = ALLOW_RETURN_HOLE;
7090 graph()->MarkDependsOnEmptyArrayProtoElements(); 5754 graph()->MarkDependsOnEmptyArrayProtoElements();
7091 } 5755 }
7092 5756
7093 return BuildUncheckedMonomorphicElementAccess( 5757 return BuildUncheckedMonomorphicElementAccess(
7094 object, key, val, 5758 object, key, val,
7095 mapcheck, map->instance_type() == JS_ARRAY_TYPE, 5759 mapcheck, map->instance_type() == JS_ARRAY_TYPE,
7096 map->elements_kind(), is_store, load_mode, store_mode); 5760 map->elements_kind(), is_store, load_mode, store_mode);
7097 } 5761 }
7098 5762
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
7210 Handle<Map> untransitionable_map; 5874 Handle<Map> untransitionable_map;
7211 HTransitionElementsKind* transition = NULL; 5875 HTransitionElementsKind* transition = NULL;
7212 for (int i = 0; i < maps->length(); ++i) { 5876 for (int i = 0; i < maps->length(); ++i) {
7213 Handle<Map> map = maps->at(i); 5877 Handle<Map> map = maps->at(i);
7214 ASSERT(map->IsMap()); 5878 ASSERT(map->IsMap());
7215 if (!transition_target.at(i).is_null()) { 5879 if (!transition_target.at(i).is_null()) {
7216 ASSERT(Map::IsValidElementsTransition( 5880 ASSERT(Map::IsValidElementsTransition(
7217 map->elements_kind(), 5881 map->elements_kind(),
7218 transition_target.at(i)->elements_kind())); 5882 transition_target.at(i)->elements_kind()));
7219 HValue* context = environment()->LookupContext(); 5883 HValue* context = environment()->LookupContext();
7220 transition = new(zone()) HTransitionElementsKind( 5884 transition = Add<HTransitionElementsKind>(context, object, map,
7221 context, object, map, transition_target.at(i)); 5885 transition_target.at(i));
7222 AddInstruction(transition);
7223 } else { 5886 } else {
7224 type_todo[map->elements_kind()] = true; 5887 type_todo[map->elements_kind()] = true;
7225 if (IsExternalArrayElementsKind(map->elements_kind())) { 5888 if (IsExternalArrayElementsKind(map->elements_kind())) {
7226 todo_external_array = true; 5889 todo_external_array = true;
7227 } 5890 }
7228 num_untransitionable_maps++; 5891 num_untransitionable_maps++;
7229 untransitionable_map = map; 5892 untransitionable_map = map;
7230 } 5893 }
7231 } 5894 }
7232 5895
(...skipping 12 matching lines...) Expand all
7245 } 5908 }
7246 *has_side_effects |= instr->HasObservableSideEffects(); 5909 *has_side_effects |= instr->HasObservableSideEffects();
7247 if (position != RelocInfo::kNoPosition) instr->set_position(position); 5910 if (position != RelocInfo::kNoPosition) instr->set_position(position);
7248 return is_store ? NULL : instr; 5911 return is_store ? NULL : instr;
7249 } 5912 }
7250 5913
7251 HInstruction* checkspec = 5914 HInstruction* checkspec =
7252 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone())); 5915 AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone()));
7253 HBasicBlock* join = graph()->CreateBasicBlock(); 5916 HBasicBlock* join = graph()->CreateBasicBlock();
7254 5917
7255 HInstruction* elements_kind_instr = 5918 HInstruction* elements_kind_instr = Add<HElementsKind>(object);
7256 AddInstruction(new(zone()) HElementsKind(object));
7257 HInstruction* elements = AddLoadElements(object, checkspec); 5919 HInstruction* elements = AddLoadElements(object, checkspec);
7258 HLoadExternalArrayPointer* external_elements = NULL; 5920 HLoadExternalArrayPointer* external_elements = NULL;
7259 HInstruction* checked_key = NULL; 5921 HInstruction* checked_key = NULL;
7260 5922
7261 // Generated code assumes that FAST_* and DICTIONARY_ELEMENTS ElementsKinds 5923 // Generated code assumes that FAST_* and DICTIONARY_ELEMENTS ElementsKinds
7262 // are handled before external arrays. 5924 // are handled before external arrays.
7263 STATIC_ASSERT(FAST_SMI_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); 5925 STATIC_ASSERT(FAST_SMI_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
7264 STATIC_ASSERT(FAST_HOLEY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); 5926 STATIC_ASSERT(FAST_HOLEY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
7265 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); 5927 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
7266 STATIC_ASSERT(DICTIONARY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); 5928 STATIC_ASSERT(DICTIONARY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
7267 5929
7268 for (ElementsKind elements_kind = FIRST_ELEMENTS_KIND; 5930 for (ElementsKind elements_kind = FIRST_ELEMENTS_KIND;
7269 elements_kind <= LAST_ELEMENTS_KIND; 5931 elements_kind <= LAST_ELEMENTS_KIND;
7270 elements_kind = ElementsKind(elements_kind + 1)) { 5932 elements_kind = ElementsKind(elements_kind + 1)) {
7271 // After having handled FAST_* and DICTIONARY_ELEMENTS, we need to add some 5933 // After having handled FAST_* and DICTIONARY_ELEMENTS, we need to add some
7272 // code that's executed for all external array cases. 5934 // code that's executed for all external array cases.
7273 STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == 5935 STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND ==
7274 LAST_ELEMENTS_KIND); 5936 LAST_ELEMENTS_KIND);
7275 if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND 5937 if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND
7276 && todo_external_array) { 5938 && todo_external_array) {
7277 HInstruction* length = 5939 HInstruction* length = AddLoadFixedArrayLength(elements);
7278 AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); 5940 checked_key = Add<HBoundsCheck>(key, length);
7279 checked_key = AddBoundsCheck(key, length); 5941 external_elements = Add<HLoadExternalArrayPointer>(elements);
7280 external_elements = new(zone()) HLoadExternalArrayPointer(elements);
7281 AddInstruction(external_elements);
7282 } 5942 }
7283 if (type_todo[elements_kind]) { 5943 if (type_todo[elements_kind]) {
7284 HBasicBlock* if_true = graph()->CreateBasicBlock(); 5944 HBasicBlock* if_true = graph()->CreateBasicBlock();
7285 HBasicBlock* if_false = graph()->CreateBasicBlock(); 5945 HBasicBlock* if_false = graph()->CreateBasicBlock();
7286 HCompareConstantEqAndBranch* elements_kind_branch = 5946 HCompareConstantEqAndBranch* elements_kind_branch =
7287 new(zone()) HCompareConstantEqAndBranch( 5947 new(zone()) HCompareConstantEqAndBranch(
7288 elements_kind_instr, elements_kind, Token::EQ_STRICT); 5948 elements_kind_instr, elements_kind, Token::EQ_STRICT);
7289 elements_kind_branch->SetSuccessorAt(0, if_true); 5949 elements_kind_branch->SetSuccessorAt(0, if_true);
7290 elements_kind_branch->SetSuccessorAt(1, if_false); 5950 elements_kind_branch->SetSuccessorAt(1, if_false);
7291 current_block()->Finish(elements_kind_branch); 5951 current_block()->Finish(elements_kind_branch);
(...skipping 20 matching lines...) Expand all
7312 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); 5972 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE);
7313 typecheck->SetSuccessorAt(0, if_jsarray); 5973 typecheck->SetSuccessorAt(0, if_jsarray);
7314 typecheck->SetSuccessorAt(1, if_fastobject); 5974 typecheck->SetSuccessorAt(1, if_fastobject);
7315 current_block()->Finish(typecheck); 5975 current_block()->Finish(typecheck);
7316 5976
7317 set_current_block(if_jsarray); 5977 set_current_block(if_jsarray);
7318 HInstruction* length = AddLoad(object, HObjectAccess::ForArrayLength(), 5978 HInstruction* length = AddLoad(object, HObjectAccess::ForArrayLength(),
7319 typecheck, Representation::Smi()); 5979 typecheck, Representation::Smi());
7320 length->set_type(HType::Smi()); 5980 length->set_type(HType::Smi());
7321 5981
7322 checked_key = AddBoundsCheck(key, length); 5982 checked_key = Add<HBoundsCheck>(key, length);
7323 access = AddInstruction(BuildFastElementAccess( 5983 access = AddInstruction(BuildFastElementAccess(
7324 elements, checked_key, val, elements_kind_branch, 5984 elements, checked_key, val, elements_kind_branch,
7325 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE)); 5985 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE));
7326 if (!is_store) { 5986 if (!is_store) {
7327 Push(access); 5987 Push(access);
7328 } 5988 }
7329 5989
7330 *has_side_effects |= access->HasObservableSideEffects(); 5990 *has_side_effects |= access->HasObservableSideEffects();
7331 // The caller will use has_side_effects and add correct Simulate. 5991 // The caller will use has_side_effects and add correct Simulate.
7332 access->SetFlag(HValue::kHasNoObservableSideEffects); 5992 access->SetFlag(HValue::kHasNoObservableSideEffects);
7333 if (position != -1) { 5993 if (position != -1) {
7334 access->set_position(position); 5994 access->set_position(position);
7335 } 5995 }
7336 if_jsarray->GotoNoSimulate(join); 5996 if_jsarray->GotoNoSimulate(join);
7337 5997
7338 set_current_block(if_fastobject); 5998 set_current_block(if_fastobject);
7339 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); 5999 length = AddLoadFixedArrayLength(elements);
7340 checked_key = AddBoundsCheck(key, length); 6000 checked_key = Add<HBoundsCheck>(key, length);
7341 access = AddInstruction(BuildFastElementAccess( 6001 access = AddInstruction(BuildFastElementAccess(
7342 elements, checked_key, val, elements_kind_branch, 6002 elements, checked_key, val, elements_kind_branch,
7343 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE)); 6003 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE));
7344 } else if (elements_kind == DICTIONARY_ELEMENTS) { 6004 } else if (elements_kind == DICTIONARY_ELEMENTS) {
7345 if (is_store) { 6005 if (is_store) {
7346 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); 6006 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val));
7347 } else { 6007 } else {
7348 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); 6008 access = AddInstruction(BuildLoadKeyedGeneric(object, key));
7349 } 6009 }
7350 } else { // External array elements. 6010 } else { // External array elements.
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
7462 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { 6122 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
7463 return false; 6123 return false;
7464 } 6124 }
7465 6125
7466 HInstruction* result = NULL; 6126 HInstruction* result = NULL;
7467 if (expr->key()->IsPropertyName()) { 6127 if (expr->key()->IsPropertyName()) {
7468 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 6128 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
7469 if (!name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("length"))) return false; 6129 if (!name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("length"))) return false;
7470 6130
7471 if (function_state()->outer() == NULL) { 6131 if (function_state()->outer() == NULL) {
7472 HInstruction* elements = AddInstruction( 6132 HInstruction* elements = Add<HArgumentsElements>(false);
7473 new(zone()) HArgumentsElements(false));
7474 result = new(zone()) HArgumentsLength(elements); 6133 result = new(zone()) HArgumentsLength(elements);
7475 } else { 6134 } else {
7476 // Number of arguments without receiver. 6135 // Number of arguments without receiver.
7477 int argument_count = environment()-> 6136 int argument_count = environment()->
7478 arguments_environment()->parameter_count() - 1; 6137 arguments_environment()->parameter_count() - 1;
7479 result = new(zone()) HConstant(argument_count); 6138 result = new(zone()) HConstant(argument_count);
7480 } 6139 }
7481 } else { 6140 } else {
7482 Push(graph()->GetArgumentsObject()); 6141 Push(graph()->GetArgumentsObject());
7483 VisitForValue(expr->key()); 6142 VisitForValue(expr->key());
7484 if (HasStackOverflow() || current_block() == NULL) return true; 6143 if (HasStackOverflow() || current_block() == NULL) return true;
7485 HValue* key = Pop(); 6144 HValue* key = Pop();
7486 Drop(1); // Arguments object. 6145 Drop(1); // Arguments object.
7487 if (function_state()->outer() == NULL) { 6146 if (function_state()->outer() == NULL) {
7488 HInstruction* elements = AddInstruction( 6147 HInstruction* elements = Add<HArgumentsElements>(false);
7489 new(zone()) HArgumentsElements(false)); 6148 HInstruction* length = Add<HArgumentsLength>(elements);
7490 HInstruction* length = AddInstruction( 6149 HInstruction* checked_key = Add<HBoundsCheck>(key, length);
7491 new(zone()) HArgumentsLength(elements));
7492 HInstruction* checked_key = AddBoundsCheck(key, length);
7493 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); 6150 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key);
7494 } else { 6151 } else {
7495 EnsureArgumentsArePushedForAccess(); 6152 EnsureArgumentsArePushedForAccess();
7496 6153
7497 // Number of arguments without receiver. 6154 // Number of arguments without receiver.
7498 HInstruction* elements = function_state()->arguments_elements(); 6155 HInstruction* elements = function_state()->arguments_elements();
7499 int argument_count = environment()-> 6156 int argument_count = environment()->
7500 arguments_environment()->parameter_count() - 1; 6157 arguments_environment()->parameter_count() - 1;
7501 HInstruction* length = AddInstruction(new(zone()) HConstant( 6158 HInstruction* length = Add<HConstant>(argument_count);
7502 argument_count)); 6159 HInstruction* checked_key = Add<HBoundsCheck>(key, length);
7503 HInstruction* checked_key = AddBoundsCheck(key, length);
7504 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); 6160 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key);
7505 } 6161 }
7506 } 6162 }
7507 ast_context()->ReturnInstruction(result, expr->id()); 6163 ast_context()->ReturnInstruction(result, expr->id());
7508 return true; 6164 return true;
7509 } 6165 }
7510 6166
7511 6167
7512 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { 6168 void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
7513 ASSERT(!HasStackOverflow()); 6169 ASSERT(!HasStackOverflow());
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
7552 } else if (object->HasMonomorphicJSObjectType()) { 6208 } else if (object->HasMonomorphicJSObjectType()) {
7553 map = object->GetMonomorphicJSObjectMap(); 6209 map = object->GetMonomorphicJSObjectMap();
7554 monomorphic = !map->is_dictionary_map(); 6210 monomorphic = !map->is_dictionary_map();
7555 } 6211 }
7556 if (monomorphic) { 6212 if (monomorphic) {
7557 Handle<JSFunction> getter; 6213 Handle<JSFunction> getter;
7558 Handle<JSObject> holder; 6214 Handle<JSObject> holder;
7559 if (LookupGetter(map, name, &getter, &holder)) { 6215 if (LookupGetter(map, name, &getter, &holder)) {
7560 AddCheckConstantFunction(holder, Top(), map); 6216 AddCheckConstantFunction(holder, Top(), map);
7561 if (FLAG_inline_accessors && TryInlineGetter(getter, expr)) return; 6217 if (FLAG_inline_accessors && TryInlineGetter(getter, expr)) return;
7562 AddInstruction(new(zone()) HPushArgument(Pop())); 6218 Add<HPushArgument>(Pop());
7563 instr = new(zone()) HCallConstantFunction(getter, 1); 6219 instr = new(zone()) HCallConstantFunction(getter, 1);
7564 } else { 6220 } else {
7565 instr = BuildLoadNamedMonomorphic(Pop(), name, expr, map); 6221 instr = BuildLoadNamedMonomorphic(Pop(), name, expr, map);
7566 } 6222 }
7567 } else if (types != NULL && types->length() > 1) { 6223 } else if (types != NULL && types->length() > 1) {
7568 return HandlePolymorphicLoadNamedField(expr, Pop(), types, name); 6224 return HandlePolymorphicLoadNamedField(expr, Pop(), types, name);
7569 } else { 6225 } else {
7570 instr = BuildLoadNamedGeneric(Pop(), name, expr); 6226 instr = BuildLoadNamedGeneric(Pop(), name, expr);
7571 } 6227 }
7572 6228
(...skipping 21 matching lines...) Expand all
7594 } 6250 }
7595 instr->set_position(expr->position()); 6251 instr->set_position(expr->position());
7596 return ast_context()->ReturnInstruction(instr, expr->id()); 6252 return ast_context()->ReturnInstruction(instr, expr->id());
7597 } 6253 }
7598 6254
7599 6255
7600 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, 6256 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder,
7601 Handle<Map> receiver_map) { 6257 Handle<Map> receiver_map) {
7602 if (!holder.is_null()) { 6258 if (!holder.is_null()) {
7603 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); 6259 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
7604 AddInstruction(new(zone()) HCheckPrototypeMaps( 6260 Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info());
7605 prototype, holder, zone(), top_info()));
7606 } 6261 }
7607 } 6262 }
7608 6263
7609 6264
7610 void HOptimizedGraphBuilder::AddCheckConstantFunction( 6265 void HOptimizedGraphBuilder::AddCheckConstantFunction(
7611 Handle<JSObject> holder, 6266 Handle<JSObject> holder,
7612 HValue* receiver, 6267 HValue* receiver,
7613 Handle<Map> receiver_map) { 6268 Handle<Map> receiver_map) {
7614 // Constant functions have the nice property that the map will change if they 6269 // Constant functions have the nice property that the map will change if they
7615 // are overwritten. Therefore it is enough to check the map of the holder and 6270 // are overwritten. Therefore it is enough to check the map of the holder and
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
7867 int nodes_added = InliningAstSize(target); 6522 int nodes_added = InliningAstSize(target);
7868 if (nodes_added == kNotInlinable) return false; 6523 if (nodes_added == kNotInlinable) return false;
7869 6524
7870 Handle<JSFunction> caller = current_info()->closure(); 6525 Handle<JSFunction> caller = current_info()->closure();
7871 6526
7872 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { 6527 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
7873 TraceInline(target, caller, "target AST is too large [early]"); 6528 TraceInline(target, caller, "target AST is too large [early]");
7874 return false; 6529 return false;
7875 } 6530 }
7876 6531
7877 #if !defined(V8_TARGET_ARCH_IA32) 6532 #if !V8_TARGET_ARCH_IA32
7878 // Target must be able to use caller's context. 6533 // Target must be able to use caller's context.
7879 CompilationInfo* outer_info = current_info(); 6534 CompilationInfo* outer_info = current_info();
7880 if (target->context() != outer_info->closure()->context() || 6535 if (target->context() != outer_info->closure()->context() ||
7881 outer_info->scope()->contains_with() || 6536 outer_info->scope()->contains_with() ||
7882 outer_info->scope()->num_heap_slots() > 0) { 6537 outer_info->scope()->num_heap_slots() > 0) {
7883 TraceInline(target, caller, "target requires context change"); 6538 TraceInline(target, caller, "target requires context change");
7884 return false; 6539 return false;
7885 } 6540 }
7886 #endif 6541 #endif
7887 6542
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
8016 HConstant* undefined = graph()->GetConstantUndefined(); 6671 HConstant* undefined = graph()->GetConstantUndefined();
8017 bool undefined_receiver = HEnvironment::UseUndefinedReceiver( 6672 bool undefined_receiver = HEnvironment::UseUndefinedReceiver(
8018 target, function, call_kind, inlining_kind); 6673 target, function, call_kind, inlining_kind);
8019 HEnvironment* inner_env = 6674 HEnvironment* inner_env =
8020 environment()->CopyForInlining(target, 6675 environment()->CopyForInlining(target,
8021 arguments_count, 6676 arguments_count,
8022 function, 6677 function,
8023 undefined, 6678 undefined,
8024 function_state()->inlining_kind(), 6679 function_state()->inlining_kind(),
8025 undefined_receiver); 6680 undefined_receiver);
8026 #ifdef V8_TARGET_ARCH_IA32 6681 #if V8_TARGET_ARCH_IA32
8027 // IA32 only, overwrite the caller's context in the deoptimization 6682 // IA32 only, overwrite the caller's context in the deoptimization
8028 // environment with the correct one. 6683 // environment with the correct one.
8029 // 6684 //
8030 // TODO(kmillikin): implement the same inlining on other platforms so we 6685 // TODO(kmillikin): implement the same inlining on other platforms so we
8031 // can remove the unsightly ifdefs in this function. 6686 // can remove the unsightly ifdefs in this function.
8032 HConstant* context = 6687 HConstant* context = Add<HConstant>(Handle<Context>(target->context()));
8033 new(zone()) HConstant(Handle<Context>(target->context()));
8034 AddInstruction(context);
8035 inner_env->BindContext(context); 6688 inner_env->BindContext(context);
8036 #endif 6689 #endif
8037 6690
8038 AddSimulate(return_id); 6691 AddSimulate(return_id);
8039 current_block()->UpdateEnvironment(inner_env); 6692 current_block()->UpdateEnvironment(inner_env);
8040 HArgumentsObject* arguments_object = NULL; 6693 HArgumentsObject* arguments_object = NULL;
8041 6694
8042 // If the function uses arguments object create and bind one, also copy 6695 // If the function uses arguments object create and bind one, also copy
8043 // current arguments values to use them for materialization. 6696 // current arguments values to use them for materialization.
8044 if (function->scope()->arguments() != NULL) { 6697 if (function->scope()->arguments() != NULL) {
8045 ASSERT(function->scope()->arguments()->IsStackAllocated()); 6698 ASSERT(function->scope()->arguments()->IsStackAllocated());
8046 HEnvironment* arguments_env = inner_env->arguments_environment(); 6699 HEnvironment* arguments_env = inner_env->arguments_environment();
8047 int arguments_count = arguments_env->parameter_count(); 6700 int arguments_count = arguments_env->parameter_count();
8048 arguments_object = new(zone()) HArgumentsObject(arguments_count, zone()); 6701 arguments_object = Add<HArgumentsObject>(arguments_count, zone());
8049 inner_env->Bind(function->scope()->arguments(), arguments_object); 6702 inner_env->Bind(function->scope()->arguments(), arguments_object);
8050 for (int i = 0; i < arguments_count; i++) { 6703 for (int i = 0; i < arguments_count; i++) {
8051 arguments_object->AddArgument(arguments_env->Lookup(i), zone()); 6704 arguments_object->AddArgument(arguments_env->Lookup(i), zone());
8052 } 6705 }
8053 AddInstruction(arguments_object);
8054 } 6706 }
8055 6707
8056 HEnterInlined* enter_inlined = 6708 HEnterInlined* enter_inlined =
8057 new(zone()) HEnterInlined(target, 6709 Add<HEnterInlined>(target, arguments_count, function,
8058 arguments_count, 6710 function_state()->inlining_kind(),
8059 function, 6711 function->scope()->arguments(),
8060 function_state()->inlining_kind(), 6712 arguments_object, undefined_receiver, zone());
8061 function->scope()->arguments(),
8062 arguments_object,
8063 undefined_receiver,
8064 zone());
8065 function_state()->set_entry(enter_inlined); 6713 function_state()->set_entry(enter_inlined);
8066 AddInstruction(enter_inlined);
8067 6714
8068 VisitDeclarations(target_info.scope()->declarations()); 6715 VisitDeclarations(target_info.scope()->declarations());
8069 VisitStatements(function->body()); 6716 VisitStatements(function->body());
8070 if (HasStackOverflow()) { 6717 if (HasStackOverflow()) {
8071 // Bail out if the inline function did, as we cannot residualize a call 6718 // Bail out if the inline function did, as we cannot residualize a call
8072 // instead. 6719 // instead.
8073 TraceInline(target, caller, "inline graph construction failed"); 6720 TraceInline(target, caller, "inline graph construction failed");
8074 target_shared->DisableOptimization("inlining bailed out"); 6721 target_shared->DisableOptimization("inlining bailed out");
8075 inline_bailout_ = true; 6722 inline_bailout_ = true;
8076 delete target_state; 6723 delete target_state;
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
8294 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 6941 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
8295 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 6942 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
8296 switch (id) { 6943 switch (id) {
8297 case kStringCharCodeAt: 6944 case kStringCharCodeAt:
8298 case kStringCharAt: 6945 case kStringCharAt:
8299 if (argument_count == 2 && check_type == STRING_CHECK) { 6946 if (argument_count == 2 && check_type == STRING_CHECK) {
8300 HValue* index = Pop(); 6947 HValue* index = Pop();
8301 HValue* string = Pop(); 6948 HValue* string = Pop();
8302 HValue* context = environment()->LookupContext(); 6949 HValue* context = environment()->LookupContext();
8303 ASSERT(!expr->holder().is_null()); 6950 ASSERT(!expr->holder().is_null());
8304 AddInstruction(new(zone()) HCheckPrototypeMaps( 6951 Add<HCheckPrototypeMaps>(Call::GetPrototypeForPrimitiveCheck(
8305 Call::GetPrototypeForPrimitiveCheck(STRING_CHECK, 6952 STRING_CHECK, expr->holder()->GetIsolate()),
8306 expr->holder()->GetIsolate()), 6953 expr->holder(), zone(), top_info());
8307 expr->holder(),
8308 zone(),
8309 top_info()));
8310 HInstruction* char_code = 6954 HInstruction* char_code =
8311 BuildStringCharCodeAt(context, string, index); 6955 BuildStringCharCodeAt(context, string, index);
8312 if (id == kStringCharCodeAt) { 6956 if (id == kStringCharCodeAt) {
8313 ast_context()->ReturnInstruction(char_code, expr->id()); 6957 ast_context()->ReturnInstruction(char_code, expr->id());
8314 return true; 6958 return true;
8315 } 6959 }
8316 AddInstruction(char_code); 6960 AddInstruction(char_code);
8317 HInstruction* result = 6961 HInstruction* result =
8318 HStringCharFromCode::New(zone(), context, char_code); 6962 HStringCharFromCode::New(zone(), context, char_code);
8319 ast_context()->ReturnInstruction(result, expr->id()); 6963 ast_context()->ReturnInstruction(result, expr->id());
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
8390 } 7034 }
8391 ast_context()->ReturnInstruction(result, expr->id()); 7035 ast_context()->ReturnInstruction(result, expr->id());
8392 return true; 7036 return true;
8393 } 7037 }
8394 break; 7038 break;
8395 case kMathRandom: 7039 case kMathRandom:
8396 if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) { 7040 if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) {
8397 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); 7041 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
8398 Drop(1); // Receiver. 7042 Drop(1); // Receiver.
8399 HValue* context = environment()->LookupContext(); 7043 HValue* context = environment()->LookupContext();
8400 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 7044 HGlobalObject* global_object = Add<HGlobalObject>(context);
8401 AddInstruction(global_object);
8402 HRandom* result = new(zone()) HRandom(global_object); 7045 HRandom* result = new(zone()) HRandom(global_object);
8403 ast_context()->ReturnInstruction(result, expr->id()); 7046 ast_context()->ReturnInstruction(result, expr->id());
8404 return true; 7047 return true;
8405 } 7048 }
8406 break; 7049 break;
8407 case kMathMax: 7050 case kMathMax:
8408 case kMathMin: 7051 case kMathMin:
8409 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { 7052 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) {
8410 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); 7053 AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
8411 HValue* right = Pop(); 7054 HValue* right = Pop();
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
8470 if (HasStackOverflow() || current_block() == NULL) return true; 7113 if (HasStackOverflow() || current_block() == NULL) return true;
8471 HValue* function = Top(); 7114 HValue* function = Top();
8472 AddCheckConstantFunction(expr->holder(), function, function_map); 7115 AddCheckConstantFunction(expr->holder(), function, function_map);
8473 Drop(1); 7116 Drop(1);
8474 7117
8475 VisitForValue(args->at(0)); 7118 VisitForValue(args->at(0));
8476 if (HasStackOverflow() || current_block() == NULL) return true; 7119 if (HasStackOverflow() || current_block() == NULL) return true;
8477 HValue* receiver = Pop(); 7120 HValue* receiver = Pop();
8478 7121
8479 if (function_state()->outer() == NULL) { 7122 if (function_state()->outer() == NULL) {
8480 HInstruction* elements = AddInstruction( 7123 HInstruction* elements = Add<HArgumentsElements>(false);
8481 new(zone()) HArgumentsElements(false)); 7124 HInstruction* length = Add<HArgumentsLength>(elements);
8482 HInstruction* length = 7125 HValue* wrapped_receiver = Add<HWrapReceiver>(receiver, function);
8483 AddInstruction(new(zone()) HArgumentsLength(elements));
8484 HValue* wrapped_receiver =
8485 AddInstruction(new(zone()) HWrapReceiver(receiver, function));
8486 HInstruction* result = 7126 HInstruction* result =
8487 new(zone()) HApplyArguments(function, 7127 new(zone()) HApplyArguments(function,
8488 wrapped_receiver, 7128 wrapped_receiver,
8489 length, 7129 length,
8490 elements); 7130 elements);
8491 result->set_position(expr->position()); 7131 result->set_position(expr->position());
8492 ast_context()->ReturnInstruction(result, expr->id()); 7132 ast_context()->ReturnInstruction(result, expr->id());
8493 return true; 7133 return true;
8494 } else { 7134 } else {
8495 // We are inside inlined function and we know exactly what is inside 7135 // We are inside inlined function and we know exactly what is inside
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
8700 if (known_global_function) { 7340 if (known_global_function) {
8701 // Push the global object instead of the global receiver because 7341 // Push the global object instead of the global receiver because
8702 // code generated by the full code generator expects it. 7342 // code generated by the full code generator expects it.
8703 HValue* context = environment()->LookupContext(); 7343 HValue* context = environment()->LookupContext();
8704 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 7344 HGlobalObject* global_object = new(zone()) HGlobalObject(context);
8705 PushAndAdd(global_object); 7345 PushAndAdd(global_object);
8706 CHECK_ALIVE(VisitExpressions(expr->arguments())); 7346 CHECK_ALIVE(VisitExpressions(expr->arguments()));
8707 7347
8708 CHECK_ALIVE(VisitForValue(expr->expression())); 7348 CHECK_ALIVE(VisitForValue(expr->expression()));
8709 HValue* function = Pop(); 7349 HValue* function = Pop();
8710 AddInstruction(new(zone()) HCheckFunction(function, expr->target())); 7350 Add<HCheckFunction>(function, expr->target());
8711 7351
8712 // Replace the global object with the global receiver. 7352 // Replace the global object with the global receiver.
8713 HGlobalReceiver* global_receiver = 7353 HGlobalReceiver* global_receiver = Add<HGlobalReceiver>(global_object);
8714 new(zone()) HGlobalReceiver(global_object);
8715 // Index of the receiver from the top of the expression stack. 7354 // Index of the receiver from the top of the expression stack.
8716 const int receiver_index = argument_count - 1; 7355 const int receiver_index = argument_count - 1;
8717 AddInstruction(global_receiver);
8718 ASSERT(environment()->ExpressionStackAt(receiver_index)-> 7356 ASSERT(environment()->ExpressionStackAt(receiver_index)->
8719 IsGlobalObject()); 7357 IsGlobalObject());
8720 environment()->SetExpressionStackAt(receiver_index, global_receiver); 7358 environment()->SetExpressionStackAt(receiver_index, global_receiver);
8721 7359
8722 if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop. 7360 if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop.
8723 if (FLAG_trace_inlining) { 7361 if (FLAG_trace_inlining) {
8724 PrintF("Inlining builtin "); 7362 PrintF("Inlining builtin ");
8725 expr->target()->ShortPrint(); 7363 expr->target()->ShortPrint();
8726 PrintF("\n"); 7364 PrintF("\n");
8727 } 7365 }
(...skipping 10 matching lines...) Expand all
8738 // because it is likely to generate better code. 7376 // because it is likely to generate better code.
8739 HValue* context = environment()->LookupContext(); 7377 HValue* context = environment()->LookupContext();
8740 call = PreProcessCall( 7378 call = PreProcessCall(
8741 new(zone()) HCallNamed(context, var->name(), argument_count)); 7379 new(zone()) HCallNamed(context, var->name(), argument_count));
8742 } else { 7380 } else {
8743 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), 7381 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(),
8744 argument_count)); 7382 argument_count));
8745 } 7383 }
8746 } else { 7384 } else {
8747 HValue* context = environment()->LookupContext(); 7385 HValue* context = environment()->LookupContext();
8748 HGlobalObject* receiver = new(zone()) HGlobalObject(context); 7386 HGlobalObject* receiver = Add<HGlobalObject>(context);
8749 AddInstruction(receiver);
8750 PushAndAdd(new(zone()) HPushArgument(receiver)); 7387 PushAndAdd(new(zone()) HPushArgument(receiver));
8751 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 7388 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
8752 7389
8753 call = new(zone()) HCallGlobal(context, var->name(), argument_count); 7390 call = new(zone()) HCallGlobal(context, var->name(), argument_count);
8754 Drop(argument_count); 7391 Drop(argument_count);
8755 } 7392 }
8756 7393
8757 } else if (expr->IsMonomorphic()) { 7394 } else if (expr->IsMonomorphic()) {
8758 // The function is on the stack in the unoptimized code during 7395 // The function is on the stack in the unoptimized code during
8759 // evaluation of the arguments. 7396 // evaluation of the arguments.
8760 CHECK_ALIVE(VisitForValue(expr->expression())); 7397 CHECK_ALIVE(VisitForValue(expr->expression()));
8761 HValue* function = Top(); 7398 HValue* function = Top();
8762 HValue* context = environment()->LookupContext(); 7399 HValue* context = environment()->LookupContext();
8763 HGlobalObject* global = new(zone()) HGlobalObject(context); 7400 HGlobalObject* global = Add<HGlobalObject>(context);
8764 AddInstruction(global);
8765 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global); 7401 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global);
8766 PushAndAdd(receiver); 7402 PushAndAdd(receiver);
8767 CHECK_ALIVE(VisitExpressions(expr->arguments())); 7403 CHECK_ALIVE(VisitExpressions(expr->arguments()));
8768 AddInstruction(new(zone()) HCheckFunction(function, expr->target())); 7404 Add<HCheckFunction>(function, expr->target());
8769 7405
8770 if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function. 7406 if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function.
8771 if (FLAG_trace_inlining) { 7407 if (FLAG_trace_inlining) {
8772 PrintF("Inlining builtin "); 7408 PrintF("Inlining builtin ");
8773 expr->target()->ShortPrint(); 7409 expr->target()->ShortPrint();
8774 PrintF("\n"); 7410 PrintF("\n");
8775 } 7411 }
8776 return; 7412 return;
8777 } 7413 }
8778 7414
8779 if (TryInlineCall(expr, true)) { // Drop function from environment. 7415 if (TryInlineCall(expr, true)) { // Drop function from environment.
8780 return; 7416 return;
8781 } else { 7417 } else {
8782 call = PreProcessCall( 7418 call = PreProcessCall(
8783 new(zone()) HInvokeFunction(context, 7419 new(zone()) HInvokeFunction(context,
8784 function, 7420 function,
8785 expr->target(), 7421 expr->target(),
8786 argument_count)); 7422 argument_count));
8787 Drop(1); // The function. 7423 Drop(1); // The function.
8788 } 7424 }
8789 7425
8790 } else { 7426 } else {
8791 CHECK_ALIVE(VisitForValue(expr->expression())); 7427 CHECK_ALIVE(VisitForValue(expr->expression()));
8792 HValue* function = Top(); 7428 HValue* function = Top();
8793 HValue* context = environment()->LookupContext(); 7429 HValue* context = environment()->LookupContext();
8794 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 7430 HGlobalObject* global_object = Add<HGlobalObject>(context);
8795 AddInstruction(global_object); 7431 HGlobalReceiver* receiver = Add<HGlobalReceiver>(global_object);
8796 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global_object);
8797 AddInstruction(receiver);
8798 PushAndAdd(new(zone()) HPushArgument(receiver)); 7432 PushAndAdd(new(zone()) HPushArgument(receiver));
8799 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 7433 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
8800 7434
8801 call = new(zone()) HCallFunction(context, function, argument_count); 7435 call = new(zone()) HCallFunction(context, function, argument_count);
8802 Drop(argument_count + 1); 7436 Drop(argument_count + 1);
8803 } 7437 }
8804 } 7438 }
8805 7439
8806 call->set_position(expr->position()); 7440 call->set_position(expr->position());
8807 return ast_context()->ReturnInstruction(call, expr->id()); 7441 return ast_context()->ReturnInstruction(call, expr->id());
(...skipping 17 matching lines...) Expand all
8825 7459
8826 if (FLAG_inline_construct && 7460 if (FLAG_inline_construct &&
8827 expr->IsMonomorphic() && 7461 expr->IsMonomorphic() &&
8828 IsAllocationInlineable(expr->target())) { 7462 IsAllocationInlineable(expr->target())) {
8829 // The constructor function is on the stack in the unoptimized code 7463 // The constructor function is on the stack in the unoptimized code
8830 // during evaluation of the arguments. 7464 // during evaluation of the arguments.
8831 CHECK_ALIVE(VisitForValue(expr->expression())); 7465 CHECK_ALIVE(VisitForValue(expr->expression()));
8832 HValue* function = Top(); 7466 HValue* function = Top();
8833 CHECK_ALIVE(VisitExpressions(expr->arguments())); 7467 CHECK_ALIVE(VisitExpressions(expr->arguments()));
8834 Handle<JSFunction> constructor = expr->target(); 7468 Handle<JSFunction> constructor = expr->target();
8835 HValue* check = AddInstruction( 7469 HValue* check = Add<HCheckFunction>(function, constructor);
8836 new(zone()) HCheckFunction(function, constructor));
8837 7470
8838 // Force completion of inobject slack tracking before generating 7471 // Force completion of inobject slack tracking before generating
8839 // allocation code to finalize instance size. 7472 // allocation code to finalize instance size.
8840 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) { 7473 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) {
8841 constructor->shared()->CompleteInobjectSlackTracking(); 7474 constructor->shared()->CompleteInobjectSlackTracking();
8842 } 7475 }
8843 7476
8844 // Replace the constructor function with a newly allocated receiver. 7477 // Replace the constructor function with a newly allocated receiver.
8845 HInstruction* receiver = new(zone()) HAllocateObject(context, constructor); 7478 HInstruction* receiver = Add<HAllocateObject>(context, constructor);
8846 // Index of the receiver from the top of the expression stack. 7479 // Index of the receiver from the top of the expression stack.
8847 const int receiver_index = argument_count - 1; 7480 const int receiver_index = argument_count - 1;
8848 AddInstruction(receiver);
8849 ASSERT(environment()->ExpressionStackAt(receiver_index) == function); 7481 ASSERT(environment()->ExpressionStackAt(receiver_index) == function);
8850 environment()->SetExpressionStackAt(receiver_index, receiver); 7482 environment()->SetExpressionStackAt(receiver_index, receiver);
8851 7483
8852 if (TryInlineConstruct(expr, receiver)) return; 7484 if (TryInlineConstruct(expr, receiver)) return;
8853 7485
8854 // TODO(mstarzinger): For now we remove the previous HAllocateObject and 7486 // TODO(mstarzinger): For now we remove the previous HAllocateObject and
8855 // add HPushArgument for the arguments in case inlining failed. What we 7487 // add HPushArgument for the arguments in case inlining failed. What we
8856 // actually should do is emit HInvokeFunction on the constructor instead 7488 // actually should do is emit HInvokeFunction on the constructor instead
8857 // of using HCallNew as a fallback. 7489 // of using HCallNew as a fallback.
8858 receiver->DeleteAndReplaceWith(NULL); 7490 receiver->DeleteAndReplaceWith(NULL);
8859 check->DeleteAndReplaceWith(NULL); 7491 check->DeleteAndReplaceWith(NULL);
8860 environment()->SetExpressionStackAt(receiver_index, function); 7492 environment()->SetExpressionStackAt(receiver_index, function);
8861 HInstruction* call = PreProcessCall( 7493 HInstruction* call = PreProcessCall(
8862 new(zone()) HCallNew(context, function, argument_count)); 7494 new(zone()) HCallNew(context, function, argument_count));
8863 call->set_position(expr->position()); 7495 call->set_position(expr->position());
8864 return ast_context()->ReturnInstruction(call, expr->id()); 7496 return ast_context()->ReturnInstruction(call, expr->id());
8865 } else { 7497 } else {
8866 // The constructor function is both an operand to the instruction and an 7498 // The constructor function is both an operand to the instruction and an
8867 // argument to the construct call. 7499 // argument to the construct call.
8868 Handle<JSFunction> array_function( 7500 Handle<JSFunction> array_function(
8869 isolate()->global_context()->array_function(), isolate()); 7501 isolate()->global_context()->array_function(), isolate());
8870 CHECK_ALIVE(VisitArgument(expr->expression())); 7502 CHECK_ALIVE(VisitArgument(expr->expression()));
8871 HValue* constructor = HPushArgument::cast(Top())->argument(); 7503 HValue* constructor = HPushArgument::cast(Top())->argument();
8872 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 7504 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
8873 HCallNew* call; 7505 HCallNew* call;
8874 if (expr->target().is_identical_to(array_function)) { 7506 if (expr->target().is_identical_to(array_function)) {
8875 Handle<Cell> cell = expr->allocation_info_cell(); 7507 Handle<Cell> cell = expr->allocation_info_cell();
8876 AddInstruction(new(zone()) HCheckFunction(constructor, array_function)); 7508 Add<HCheckFunction>(constructor, array_function);
8877 call = new(zone()) HCallNewArray(context, constructor, argument_count, 7509 call = new(zone()) HCallNewArray(context, constructor, argument_count,
8878 cell); 7510 cell, expr->elements_kind());
8879 } else { 7511 } else {
8880 call = new(zone()) HCallNew(context, constructor, argument_count); 7512 call = new(zone()) HCallNew(context, constructor, argument_count);
8881 } 7513 }
8882 Drop(argument_count); 7514 Drop(argument_count);
8883 call->set_position(expr->position()); 7515 call->set_position(expr->position());
8884 return ast_context()->ReturnInstruction(call, expr->id()); 7516 return ast_context()->ReturnInstruction(call, expr->id());
8885 } 7517 }
8886 } 7518 }
8887 7519
8888 7520
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
9002 HValue* value = Pop(); 7634 HValue* value = Pop();
9003 HValue* context = environment()->LookupContext(); 7635 HValue* context = environment()->LookupContext();
9004 HInstruction* instr = new(zone()) HTypeof(context, value); 7636 HInstruction* instr = new(zone()) HTypeof(context, value);
9005 return ast_context()->ReturnInstruction(instr, expr->id()); 7637 return ast_context()->ReturnInstruction(instr, expr->id());
9006 } 7638 }
9007 7639
9008 7640
9009 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { 7641 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) {
9010 CHECK_ALIVE(VisitForValue(expr->expression())); 7642 CHECK_ALIVE(VisitForValue(expr->expression()));
9011 HValue* value = Pop(); 7643 HValue* value = Pop();
9012 HValue* context = environment()->LookupContext();
9013 HInstruction* instr =
9014 HMul::New(zone(), context, value, graph()->GetConstantMinus1());
9015 Handle<Type> operand_type = expr->expression()->lower_type(); 7644 Handle<Type> operand_type = expr->expression()->lower_type();
9016 Representation rep = ToRepresentation(operand_type); 7645 HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::SUB);
9017 if (operand_type->Is(Type::None())) {
9018 AddSoftDeoptimize();
9019 }
9020 if (instr->IsBinaryOperation()) {
9021 HBinaryOperation::cast(instr)->set_observed_input_representation(1, rep);
9022 HBinaryOperation::cast(instr)->set_observed_input_representation(2, rep);
9023 }
9024 return ast_context()->ReturnInstruction(instr, expr->id()); 7646 return ast_context()->ReturnInstruction(instr, expr->id());
9025 } 7647 }
9026 7648
9027 7649
9028 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { 7650 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) {
9029 CHECK_ALIVE(VisitForValue(expr->expression())); 7651 CHECK_ALIVE(VisitForValue(expr->expression()));
9030 HValue* value = Pop(); 7652 HValue* value = Pop();
9031 Handle<Type> operand_type = expr->expression()->lower_type(); 7653 Handle<Type> operand_type = expr->expression()->lower_type();
9032 if (operand_type->Is(Type::None())) { 7654 HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::BIT_NOT);
9033 AddSoftDeoptimize();
9034 }
9035 HInstruction* instr = new(zone()) HBitNot(value);
9036 return ast_context()->ReturnInstruction(instr, expr->id()); 7655 return ast_context()->ReturnInstruction(instr, expr->id());
9037 } 7656 }
9038 7657
9039 7658
9040 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { 7659 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) {
9041 if (ast_context()->IsTest()) { 7660 if (ast_context()->IsTest()) {
9042 TestContext* context = TestContext::cast(ast_context()); 7661 TestContext* context = TestContext::cast(ast_context());
9043 VisitForControl(expr->expression(), 7662 VisitForControl(expr->expression(),
9044 context->if_false(), 7663 context->if_false(),
9045 context->if_true()); 7664 context->if_true());
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
9079 set_current_block(join); 7698 set_current_block(join);
9080 if (join != NULL) return ast_context()->ReturnValue(Pop()); 7699 if (join != NULL) return ast_context()->ReturnValue(Pop());
9081 } 7700 }
9082 7701
9083 7702
9084 HInstruction* HOptimizedGraphBuilder::BuildIncrement( 7703 HInstruction* HOptimizedGraphBuilder::BuildIncrement(
9085 bool returns_original_input, 7704 bool returns_original_input,
9086 CountOperation* expr) { 7705 CountOperation* expr) {
9087 // The input to the count operation is on top of the expression stack. 7706 // The input to the count operation is on top of the expression stack.
9088 TypeInfo info = expr->type(); 7707 TypeInfo info = expr->type();
9089 Representation rep = ToRepresentation(info); 7708 Representation rep = Representation::FromType(info);
9090 if (rep.IsNone() || rep.IsTagged()) { 7709 if (rep.IsNone() || rep.IsTagged()) {
9091 rep = Representation::Smi(); 7710 rep = Representation::Smi();
9092 } 7711 }
9093 7712
9094 if (returns_original_input) { 7713 if (returns_original_input) {
9095 // We need an explicit HValue representing ToNumber(input). The 7714 // We need an explicit HValue representing ToNumber(input). The
9096 // actual HChange instruction we need is (sometimes) added in a later 7715 // actual HChange instruction we need is (sometimes) added in a later
9097 // phase, so it is not available now to be used as an input to HAdd and 7716 // phase, so it is not available now to be used as an input to HAdd and
9098 // as the return value. 7717 // as the return value.
9099 HInstruction* number_input = new(zone()) HForceRepresentation(Pop(), rep); 7718 HInstruction* number_input = Add<HForceRepresentation>(Pop(), rep);
9100 if (!rep.IsDouble()) { 7719 if (!rep.IsDouble()) {
9101 number_input->SetFlag(HInstruction::kFlexibleRepresentation); 7720 number_input->SetFlag(HInstruction::kFlexibleRepresentation);
9102 number_input->SetFlag(HInstruction::kCannotBeTagged); 7721 number_input->SetFlag(HInstruction::kCannotBeTagged);
9103 } 7722 }
9104 AddInstruction(number_input);
9105 Push(number_input); 7723 Push(number_input);
9106 } 7724 }
9107 7725
9108 // The addition has no side effects, so we do not need 7726 // The addition has no side effects, so we do not need
9109 // to simulate the expression stack after this instruction. 7727 // to simulate the expression stack after this instruction.
9110 // Any later failures deopt to the load of the input or earlier. 7728 // Any later failures deopt to the load of the input or earlier.
9111 HConstant* delta = (expr->op() == Token::INC) 7729 HConstant* delta = (expr->op() == Token::INC)
9112 ? graph()->GetConstant1() 7730 ? graph()->GetConstant1()
9113 : graph()->GetConstantMinus1(); 7731 : graph()->GetConstantMinus1();
9114 HValue* context = environment()->LookupContext(); 7732 HValue* context = environment()->LookupContext();
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
9177 for (int i = 0; i < count; ++i) { 7795 for (int i = 0; i < count; ++i) {
9178 if (var == current_info()->scope()->parameter(i)) { 7796 if (var == current_info()->scope()->parameter(i)) {
9179 return Bailout("assignment to parameter in arguments object"); 7797 return Bailout("assignment to parameter in arguments object");
9180 } 7798 }
9181 } 7799 }
9182 } 7800 }
9183 7801
9184 HValue* context = BuildContextChainWalk(var); 7802 HValue* context = BuildContextChainWalk(var);
9185 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode()) 7803 HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode())
9186 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; 7804 ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck;
9187 HStoreContextSlot* instr = 7805 HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(),
9188 new(zone()) HStoreContextSlot(context, var->index(), mode, after); 7806 mode, after);
9189 AddInstruction(instr);
9190 if (instr->HasObservableSideEffects()) { 7807 if (instr->HasObservableSideEffects()) {
9191 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); 7808 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE);
9192 } 7809 }
9193 break; 7810 break;
9194 } 7811 }
9195 7812
9196 case Variable::LOOKUP: 7813 case Variable::LOOKUP:
9197 return Bailout("lookup variable in count operation"); 7814 return Bailout("lookup variable in count operation");
9198 } 7815 }
9199 7816
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
9318 if (i < 0 || i >= s->length()) { 7935 if (i < 0 || i >= s->length()) {
9319 return new(zone()) HConstant(OS::nan_value()); 7936 return new(zone()) HConstant(OS::nan_value());
9320 } 7937 }
9321 return new(zone()) HConstant(s->Get(i)); 7938 return new(zone()) HConstant(s->Get(i));
9322 } 7939 }
9323 } 7940 }
9324 BuildCheckHeapObject(string); 7941 BuildCheckHeapObject(string);
9325 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); 7942 AddInstruction(HCheckInstanceType::NewIsString(string, zone()));
9326 HInstruction* length = HStringLength::New(zone(), string); 7943 HInstruction* length = HStringLength::New(zone(), string);
9327 AddInstruction(length); 7944 AddInstruction(length);
9328 HInstruction* checked_index = AddBoundsCheck(index, length); 7945 HInstruction* checked_index = Add<HBoundsCheck>(index, length);
9329 return new(zone()) HStringCharCodeAt(context, string, checked_index); 7946 return new(zone()) HStringCharCodeAt(context, string, checked_index);
9330 } 7947 }
9331 7948
7949
9332 // Checks if the given shift amounts have form: (sa) and (32 - sa). 7950 // Checks if the given shift amounts have form: (sa) and (32 - sa).
9333 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, 7951 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa,
9334 HValue* const32_minus_sa) { 7952 HValue* const32_minus_sa) {
9335 if (!const32_minus_sa->IsSub()) return false; 7953 if (!const32_minus_sa->IsSub()) return false;
9336 HSub* sub = HSub::cast(const32_minus_sa); 7954 HSub* sub = HSub::cast(const32_minus_sa);
9337 if (sa != sub->right()) return false; 7955 if (sa != sub->right()) return false;
9338 HValue* const32 = sub->left(); 7956 HValue* const32 = sub->left();
9339 if (!const32->IsConstant() || 7957 if (!const32->IsConstant() ||
9340 HConstant::cast(const32)->Integer32Value() != 32) { 7958 HConstant::cast(const32)->Integer32Value() != 32) {
9341 return false; 7959 return false;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
9389 8007
9390 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( 8008 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation(
9391 BinaryOperation* expr, 8009 BinaryOperation* expr,
9392 HValue* left, 8010 HValue* left,
9393 HValue* right) { 8011 HValue* right) {
9394 HValue* context = environment()->LookupContext(); 8012 HValue* context = environment()->LookupContext();
9395 Handle<Type> left_type = expr->left()->lower_type(); 8013 Handle<Type> left_type = expr->left()->lower_type();
9396 Handle<Type> right_type = expr->right()->lower_type(); 8014 Handle<Type> right_type = expr->right()->lower_type();
9397 Handle<Type> result_type = expr->lower_type(); 8015 Handle<Type> result_type = expr->lower_type();
9398 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); 8016 Maybe<int> fixed_right_arg = expr->fixed_right_arg();
9399 Representation left_rep = ToRepresentation(left_type); 8017 Representation left_rep = Representation::FromType(left_type);
9400 Representation right_rep = ToRepresentation(right_type); 8018 Representation right_rep = Representation::FromType(right_type);
9401 Representation result_rep = ToRepresentation(result_type); 8019 Representation result_rep = Representation::FromType(result_type);
8020
9402 if (left_type->Is(Type::None())) { 8021 if (left_type->Is(Type::None())) {
9403 AddSoftDeoptimize(); 8022 AddSoftDeoptimize();
9404 // TODO(rossberg): we should be able to get rid of non-continuous defaults. 8023 // TODO(rossberg): we should be able to get rid of non-continuous defaults.
9405 left_type = handle(Type::Any(), isolate()); 8024 left_type = handle(Type::Any(), isolate());
9406 } 8025 }
9407 if (right_type->Is(Type::None())) { 8026 if (right_type->Is(Type::None())) {
9408 AddSoftDeoptimize(); 8027 AddSoftDeoptimize();
9409 right_type = handle(Type::Any(), isolate()); 8028 right_type = handle(Type::Any(), isolate());
9410 } 8029 }
9411 HInstruction* instr = NULL; 8030 HInstruction* instr = NULL;
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
9552 CHECK_ALIVE(VisitForValue(expr->right())); 8171 CHECK_ALIVE(VisitForValue(expr->right()));
9553 } 8172 }
9554 return ast_context()->ReturnValue(Pop()); 8173 return ast_context()->ReturnValue(Pop());
9555 } 8174 }
9556 8175
9557 // We need an extra block to maintain edge-split form. 8176 // We need an extra block to maintain edge-split form.
9558 HBasicBlock* empty_block = graph()->CreateBasicBlock(); 8177 HBasicBlock* empty_block = graph()->CreateBasicBlock();
9559 HBasicBlock* eval_right = graph()->CreateBasicBlock(); 8178 HBasicBlock* eval_right = graph()->CreateBasicBlock();
9560 ToBooleanStub::Types expected(expr->left()->to_boolean_types()); 8179 ToBooleanStub::Types expected(expr->left()->to_boolean_types());
9561 HBranch* test = is_logical_and 8180 HBranch* test = is_logical_and
9562 ? new(zone()) HBranch(left_value, eval_right, empty_block, expected) 8181 ? new(zone()) HBranch(left_value, expected, eval_right, empty_block)
9563 : new(zone()) HBranch(left_value, empty_block, eval_right, expected); 8182 : new(zone()) HBranch(left_value, expected, empty_block, eval_right);
9564 current_block()->Finish(test); 8183 current_block()->Finish(test);
9565 8184
9566 set_current_block(eval_right); 8185 set_current_block(eval_right);
9567 Drop(1); // Value of the left subexpression. 8186 Drop(1); // Value of the left subexpression.
9568 CHECK_BAILOUT(VisitForValue(expr->right())); 8187 CHECK_BAILOUT(VisitForValue(expr->right()));
9569 8188
9570 HBasicBlock* join_block = 8189 HBasicBlock* join_block =
9571 CreateJoin(empty_block, current_block(), expr->id()); 8190 CreateJoin(empty_block, current_block(), expr->id());
9572 set_current_block(join_block); 8191 set_current_block(join_block);
9573 return ast_context()->ReturnValue(Pop()); 8192 return ast_context()->ReturnValue(Pop());
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
9619 CHECK_ALIVE(VisitForValue(expr->left())); 8238 CHECK_ALIVE(VisitForValue(expr->left()));
9620 CHECK_ALIVE(VisitForValue(expr->right())); 8239 CHECK_ALIVE(VisitForValue(expr->right()));
9621 HValue* right = Pop(); 8240 HValue* right = Pop();
9622 HValue* left = Pop(); 8241 HValue* left = Pop();
9623 HInstruction* instr = BuildBinaryOperation(expr, left, right); 8242 HInstruction* instr = BuildBinaryOperation(expr, left, right);
9624 instr->set_position(expr->position()); 8243 instr->set_position(expr->position());
9625 return ast_context()->ReturnInstruction(instr, expr->id()); 8244 return ast_context()->ReturnInstruction(instr, expr->id());
9626 } 8245 }
9627 8246
9628 8247
9629 // TODO(rossberg): this should die eventually.
9630 Representation HOptimizedGraphBuilder::ToRepresentation(TypeInfo info) {
9631 if (info.IsUninitialized()) return Representation::None();
9632 // TODO(verwaest): Return Smi rather than Integer32.
9633 if (info.IsSmi()) return Representation::Integer32();
9634 if (info.IsInteger32()) return Representation::Integer32();
9635 if (info.IsDouble()) return Representation::Double();
9636 if (info.IsNumber()) return Representation::Double();
9637 return Representation::Tagged();
9638 }
9639
9640
9641 Representation HOptimizedGraphBuilder::ToRepresentation(Handle<Type> type) {
9642 if (type->Is(Type::None())) return Representation::None();
9643 if (type->Is(Type::Signed32())) return Representation::Integer32();
9644 if (type->Is(Type::Number())) return Representation::Double();
9645 return Representation::Tagged();
9646 }
9647
9648
9649 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, 8248 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
9650 HTypeof* typeof_expr, 8249 HTypeof* typeof_expr,
9651 Handle<String> check) { 8250 Handle<String> check) {
9652 // Note: The HTypeof itself is removed during canonicalization, if possible. 8251 // Note: The HTypeof itself is removed during canonicalization, if possible.
9653 HValue* value = typeof_expr->value(); 8252 HValue* value = typeof_expr->value();
9654 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); 8253 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check);
9655 instr->set_position(expr->position()); 8254 instr->set_position(expr->position());
9656 return ast_context()->ReturnControl(instr, expr->id()); 8255 return ast_context()->ReturnControl(instr, expr->id());
9657 } 8256 }
9658 8257
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
9731 Handle<String> rhs = Handle<String>::cast(literal->value()); 8330 Handle<String> rhs = Handle<String>::cast(literal->value());
9732 HClassOfTestAndBranch* instr = 8331 HClassOfTestAndBranch* instr =
9733 new(zone()) HClassOfTestAndBranch(value, rhs); 8332 new(zone()) HClassOfTestAndBranch(value, rhs);
9734 instr->set_position(expr->position()); 8333 instr->set_position(expr->position());
9735 return ast_context()->ReturnControl(instr, expr->id()); 8334 return ast_context()->ReturnControl(instr, expr->id());
9736 } 8335 }
9737 8336
9738 Handle<Type> left_type = expr->left()->lower_type(); 8337 Handle<Type> left_type = expr->left()->lower_type();
9739 Handle<Type> right_type = expr->right()->lower_type(); 8338 Handle<Type> right_type = expr->right()->lower_type();
9740 Handle<Type> combined_type = expr->combined_type(); 8339 Handle<Type> combined_type = expr->combined_type();
9741 Representation combined_rep = ToRepresentation(combined_type); 8340 Representation combined_rep = Representation::FromType(combined_type);
9742 Representation left_rep = ToRepresentation(left_type); 8341 Representation left_rep = Representation::FromType(left_type);
9743 Representation right_rep = ToRepresentation(right_type); 8342 Representation right_rep = Representation::FromType(right_type);
9744 // Check if this expression was ever executed according to type feedback.
9745 // Note that for the special typeof/null/undefined cases we get unknown here.
9746 if (combined_type->Is(Type::None())) {
9747 AddSoftDeoptimize();
9748 combined_type = left_type = right_type = handle(Type::Any(), isolate());
9749 }
9750 8343
9751 CHECK_ALIVE(VisitForValue(expr->left())); 8344 CHECK_ALIVE(VisitForValue(expr->left()));
9752 CHECK_ALIVE(VisitForValue(expr->right())); 8345 CHECK_ALIVE(VisitForValue(expr->right()));
9753 8346
9754 HValue* context = environment()->LookupContext(); 8347 HValue* context = environment()->LookupContext();
9755 HValue* right = Pop(); 8348 HValue* right = Pop();
9756 HValue* left = Pop(); 8349 HValue* left = Pop();
9757 Token::Value op = expr->op(); 8350 Token::Value op = expr->op();
9758 8351
9759 HTypeof* typeof_expr = NULL; 8352 HTypeof* typeof_expr = NULL;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
9800 } 8393 }
9801 } 8394 }
9802 8395
9803 // If the target is not null we have found a known global function that is 8396 // If the target is not null we have found a known global function that is
9804 // assumed to stay the same for this instanceof. 8397 // assumed to stay the same for this instanceof.
9805 if (target.is_null()) { 8398 if (target.is_null()) {
9806 HInstanceOf* result = new(zone()) HInstanceOf(context, left, right); 8399 HInstanceOf* result = new(zone()) HInstanceOf(context, left, right);
9807 result->set_position(expr->position()); 8400 result->set_position(expr->position());
9808 return ast_context()->ReturnInstruction(result, expr->id()); 8401 return ast_context()->ReturnInstruction(result, expr->id());
9809 } else { 8402 } else {
9810 AddInstruction(new(zone()) HCheckFunction(right, target)); 8403 Add<HCheckFunction>(right, target);
9811 HInstanceOfKnownGlobal* result = 8404 HInstanceOfKnownGlobal* result =
9812 new(zone()) HInstanceOfKnownGlobal(context, left, target); 8405 new(zone()) HInstanceOfKnownGlobal(context, left, target);
9813 result->set_position(expr->position()); 8406 result->set_position(expr->position());
9814 return ast_context()->ReturnInstruction(result, expr->id()); 8407 return ast_context()->ReturnInstruction(result, expr->id());
9815 } 8408 }
8409
8410 // Code below assumes that we don't fall through.
8411 UNREACHABLE();
9816 } else if (op == Token::IN) { 8412 } else if (op == Token::IN) {
9817 HIn* result = new(zone()) HIn(context, left, right); 8413 HIn* result = new(zone()) HIn(context, left, right);
9818 result->set_position(expr->position()); 8414 result->set_position(expr->position());
9819 return ast_context()->ReturnInstruction(result, expr->id()); 8415 return ast_context()->ReturnInstruction(result, expr->id());
9820 } else if (combined_type->Is(Type::Receiver())) { 8416 }
8417
8418 // Cases handled below depend on collected type feedback. They should
8419 // soft deoptimize when there is no type feedback.
8420 if (combined_type->Is(Type::None())) {
8421 AddSoftDeoptimize();
8422 combined_type = left_type = right_type = handle(Type::Any(), isolate());
8423 }
8424
8425 if (combined_type->Is(Type::Receiver())) {
9821 switch (op) { 8426 switch (op) {
9822 case Token::EQ: 8427 case Token::EQ:
9823 case Token::EQ_STRICT: { 8428 case Token::EQ_STRICT: {
9824 // Can we get away with map check and not instance type check? 8429 // Can we get away with map check and not instance type check?
9825 if (combined_type->IsClass()) { 8430 if (combined_type->IsClass()) {
9826 Handle<Map> map = combined_type->AsClass(); 8431 Handle<Map> map = combined_type->AsClass();
9827 AddCheckMapsWithTransitions(left, map); 8432 AddCheckMapsWithTransitions(left, map);
9828 AddCheckMapsWithTransitions(right, map); 8433 AddCheckMapsWithTransitions(right, map);
9829 HCompareObjectEqAndBranch* result = 8434 HCompareObjectEqAndBranch* result =
9830 new(zone()) HCompareObjectEqAndBranch(left, right); 8435 new(zone()) HCompareObjectEqAndBranch(left, right);
(...skipping 25 matching lines...) Expand all
9856 return ast_context()->ReturnControl(result, expr->id()); 8461 return ast_context()->ReturnControl(result, expr->id());
9857 } else { 8462 } else {
9858 if (combined_rep.IsTagged() || combined_rep.IsNone()) { 8463 if (combined_rep.IsTagged() || combined_rep.IsNone()) {
9859 HCompareGeneric* result = 8464 HCompareGeneric* result =
9860 new(zone()) HCompareGeneric(context, left, right, op); 8465 new(zone()) HCompareGeneric(context, left, right, op);
9861 result->set_observed_input_representation(1, left_rep); 8466 result->set_observed_input_representation(1, left_rep);
9862 result->set_observed_input_representation(2, right_rep); 8467 result->set_observed_input_representation(2, right_rep);
9863 result->set_position(expr->position()); 8468 result->set_position(expr->position());
9864 return ast_context()->ReturnInstruction(result, expr->id()); 8469 return ast_context()->ReturnInstruction(result, expr->id());
9865 } else { 8470 } else {
9866 // TODO(verwaest): Remove once ToRepresentation properly returns Smi when 8471 // TODO(verwaest): Remove once Representation::FromType properly
9867 // the IC measures Smi. 8472 // returns Smi when the IC measures Smi.
9868 if (left_type->Is(Type::Smi())) left_rep = Representation::Smi(); 8473 if (left_type->Is(Type::Smi())) left_rep = Representation::Smi();
9869 if (right_type->Is(Type::Smi())) right_rep = Representation::Smi(); 8474 if (right_type->Is(Type::Smi())) right_rep = Representation::Smi();
9870 HCompareIDAndBranch* result = 8475 HCompareNumericAndBranch* result =
9871 new(zone()) HCompareIDAndBranch(left, right, op); 8476 new(zone()) HCompareNumericAndBranch(left, right, op);
9872 result->set_observed_input_representation(left_rep, right_rep); 8477 result->set_observed_input_representation(left_rep, right_rep);
9873 result->set_position(expr->position()); 8478 result->set_position(expr->position());
9874 return ast_context()->ReturnControl(result, expr->id()); 8479 return ast_context()->ReturnControl(result, expr->id());
9875 } 8480 }
9876 } 8481 }
9877 } 8482 }
9878 8483
9879 8484
9880 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, 8485 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
9881 HValue* value, 8486 HValue* value,
(...skipping 29 matching lines...) Expand all
9911 } else { 8516 } else {
9912 return new(zone()) HThisFunction; 8517 return new(zone()) HThisFunction;
9913 } 8518 }
9914 } 8519 }
9915 8520
9916 8521
9917 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( 8522 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
9918 HValue* context, 8523 HValue* context,
9919 Handle<JSObject> boilerplate_object, 8524 Handle<JSObject> boilerplate_object,
9920 Handle<JSObject> original_boilerplate_object, 8525 Handle<JSObject> original_boilerplate_object,
8526 Handle<Object> allocation_site,
9921 int data_size, 8527 int data_size,
9922 int pointer_size, 8528 int pointer_size,
9923 AllocationSiteMode mode) { 8529 AllocationSiteMode mode) {
9924 Zone* zone = this->zone();
9925 NoObservableSideEffectsScope no_effects(this); 8530 NoObservableSideEffectsScope no_effects(this);
9926 8531
9927 HInstruction* target = NULL; 8532 HInstruction* target = NULL;
9928 HInstruction* data_target = NULL; 8533 HInstruction* data_target = NULL;
9929 8534
9930 HAllocate::Flags flags = HAllocate::DefaultFlags(); 8535 HAllocate::Flags flags = HAllocate::DefaultFlags();
9931 8536
9932 if (isolate()->heap()->ShouldGloballyPretenure()) { 8537 if (isolate()->heap()->ShouldGloballyPretenure()) {
9933 if (data_size != 0) { 8538 if (data_size != 0) {
9934 HAllocate::Flags data_flags = 8539 HAllocate::Flags data_flags =
9935 static_cast<HAllocate::Flags>(HAllocate::DefaultFlags() | 8540 static_cast<HAllocate::Flags>(HAllocate::DefaultFlags() |
9936 HAllocate::CAN_ALLOCATE_IN_OLD_DATA_SPACE); 8541 HAllocate::CAN_ALLOCATE_IN_OLD_DATA_SPACE);
9937 HValue* size_in_bytes = AddInstruction(new(zone) HConstant(data_size)); 8542 HValue* size_in_bytes = Add<HConstant>(data_size);
9938 data_target = AddInstruction(new(zone) HAllocate( 8543 data_target = Add<HAllocate>(context, size_in_bytes,
9939 context, size_in_bytes, HType::JSObject(), data_flags)); 8544 HType::JSObject(), data_flags);
9940 Handle<Map> free_space_map = isolate()->factory()->free_space_map(); 8545 Handle<Map> free_space_map = isolate()->factory()->free_space_map();
9941 AddStoreMapConstant(data_target, free_space_map); 8546 AddStoreMapConstant(data_target, free_space_map);
9942 HObjectAccess access = 8547 HObjectAccess access =
9943 HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset); 8548 HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset);
9944 AddStore(data_target, access, size_in_bytes); 8549 AddStore(data_target, access, size_in_bytes);
9945 } 8550 }
9946 if (pointer_size != 0) { 8551 if (pointer_size != 0) {
9947 flags = static_cast<HAllocate::Flags>( 8552 flags = static_cast<HAllocate::Flags>(
9948 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); 8553 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE);
9949 HValue* size_in_bytes = AddInstruction(new(zone) HConstant(pointer_size)); 8554 HValue* size_in_bytes = Add<HConstant>(pointer_size);
9950 target = AddInstruction(new(zone) HAllocate(context, 8555 target = Add<HAllocate>(context, size_in_bytes, HType::JSObject(), flags);
9951 size_in_bytes, HType::JSObject(), flags));
9952 } 8556 }
9953 } else { 8557 } else {
9954 HValue* size_in_bytes = 8558 HValue* size_in_bytes = Add<HConstant>(data_size + pointer_size);
9955 AddInstruction(new(zone) HConstant(data_size + pointer_size)); 8559 target = Add<HAllocate>(context, size_in_bytes, HType::JSObject(), flags);
9956 target = AddInstruction(new(zone) HAllocate(context, size_in_bytes,
9957 HType::JSObject(), flags));
9958 } 8560 }
9959 8561
9960 int offset = 0; 8562 int offset = 0;
9961 int data_offset = 0; 8563 int data_offset = 0;
9962 BuildEmitDeepCopy(boilerplate_object, original_boilerplate_object, target, 8564 BuildEmitDeepCopy(boilerplate_object, original_boilerplate_object,
9963 &offset, data_target, &data_offset, mode); 8565 allocation_site, target, &offset, data_target,
8566 &data_offset, mode);
9964 return target; 8567 return target;
9965 } 8568 }
9966 8569
9967 8570
9968 void HOptimizedGraphBuilder::BuildEmitDeepCopy( 8571 void HOptimizedGraphBuilder::BuildEmitDeepCopy(
9969 Handle<JSObject> boilerplate_object, 8572 Handle<JSObject> boilerplate_object,
9970 Handle<JSObject> original_boilerplate_object, 8573 Handle<JSObject> original_boilerplate_object,
8574 Handle<Object> allocation_site_object,
9971 HInstruction* target, 8575 HInstruction* target,
9972 int* offset, 8576 int* offset,
9973 HInstruction* data_target, 8577 HInstruction* data_target,
9974 int* data_offset, 8578 int* data_offset,
9975 AllocationSiteMode mode) { 8579 AllocationSiteMode mode) {
9976 Zone* zone = this->zone(); 8580 Zone* zone = this->zone();
9977 8581
8582 bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE &&
8583 boilerplate_object->map()->CanTrackAllocationSite();
8584
8585 // If using allocation sites, then the payload on the site should already
8586 // be filled in as a valid (boilerplate) array.
8587 ASSERT(!create_allocation_site_info ||
8588 AllocationSite::cast(*allocation_site_object)->IsLiteralSite());
8589
8590 HInstruction* allocation_site = NULL;
8591
8592 if (create_allocation_site_info) {
8593 allocation_site = AddInstruction(new(zone) HConstant(
8594 allocation_site_object, Representation::Tagged()));
8595 }
8596
8597 // Only elements backing stores for non-COW arrays need to be copied.
9978 Handle<FixedArrayBase> elements(boilerplate_object->elements()); 8598 Handle<FixedArrayBase> elements(boilerplate_object->elements());
9979 Handle<FixedArrayBase> original_elements( 8599 Handle<FixedArrayBase> original_elements(
9980 original_boilerplate_object->elements()); 8600 original_boilerplate_object->elements());
9981 ElementsKind kind = boilerplate_object->map()->elements_kind(); 8601 ElementsKind kind = boilerplate_object->map()->elements_kind();
9982 8602
9983 int object_offset = *offset; 8603 int object_offset = *offset;
9984 int object_size = boilerplate_object->map()->instance_size(); 8604 int object_size = boilerplate_object->map()->instance_size();
9985 int elements_size = (elements->length() > 0 && 8605 int elements_size = (elements->length() > 0 &&
9986 elements->map() != isolate()->heap()->fixed_cow_array_map()) ? 8606 elements->map() != isolate()->heap()->fixed_cow_array_map()) ?
9987 elements->Size() : 0; 8607 elements->Size() : 0;
(...skipping 13 matching lines...) Expand all
10001 8621
10002 // Copy object elements if non-COW. 8622 // Copy object elements if non-COW.
10003 HValue* object_elements = BuildEmitObjectHeader(boilerplate_object, target, 8623 HValue* object_elements = BuildEmitObjectHeader(boilerplate_object, target,
10004 data_target, object_offset, elements_offset, elements_size); 8624 data_target, object_offset, elements_offset, elements_size);
10005 if (object_elements != NULL) { 8625 if (object_elements != NULL) {
10006 BuildEmitElements(elements, original_elements, kind, object_elements, 8626 BuildEmitElements(elements, original_elements, kind, object_elements,
10007 target, offset, data_target, data_offset); 8627 target, offset, data_target, data_offset);
10008 } 8628 }
10009 8629
10010 // Copy in-object properties. 8630 // Copy in-object properties.
10011 HValue* object_properties = 8631 if (boilerplate_object->map()->NumberOfFields() != 0) {
10012 AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset)); 8632 HValue* object_properties =
10013 BuildEmitInObjectProperties(boilerplate_object, original_boilerplate_object, 8633 Add<HInnerAllocatedObject>(target, object_offset);
10014 object_properties, target, offset, data_target, data_offset); 8634 BuildEmitInObjectProperties(boilerplate_object, original_boilerplate_object,
8635 object_properties, target, offset, data_target, data_offset);
8636 }
10015 8637
10016 // Create allocation site info. 8638 // Create allocation site info.
10017 if (mode == TRACK_ALLOCATION_SITE && 8639 if (mode == TRACK_ALLOCATION_SITE &&
10018 boilerplate_object->map()->CanTrackAllocationSite()) { 8640 boilerplate_object->map()->CanTrackAllocationSite()) {
10019 elements_offset += AllocationSiteInfo::kSize; 8641 elements_offset += AllocationSiteInfo::kSize;
10020 *offset += AllocationSiteInfo::kSize; 8642 *offset += AllocationSiteInfo::kSize;
10021 HInstruction* original_boilerplate = AddInstruction(new(zone) HConstant( 8643 BuildCreateAllocationSiteInfo(target, JSArray::kSize, allocation_site);
10022 original_boilerplate_object));
10023 BuildCreateAllocationSiteInfo(target, JSArray::kSize, original_boilerplate);
10024 } 8644 }
10025 } 8645 }
10026 8646
10027 8647
10028 HValue* HOptimizedGraphBuilder::BuildEmitObjectHeader( 8648 HValue* HOptimizedGraphBuilder::BuildEmitObjectHeader(
10029 Handle<JSObject> boilerplate_object, 8649 Handle<JSObject> boilerplate_object,
10030 HInstruction* target, 8650 HInstruction* target,
10031 HInstruction* data_target, 8651 HInstruction* data_target,
10032 int object_offset, 8652 int object_offset,
10033 int elements_offset, 8653 int elements_offset,
10034 int elements_size) { 8654 int elements_size) {
10035 ASSERT(boilerplate_object->properties()->length() == 0); 8655 ASSERT(boilerplate_object->properties()->length() == 0);
10036 Zone* zone = this->zone();
10037 HValue* result = NULL; 8656 HValue* result = NULL;
10038 8657
10039 HValue* object_header = 8658 HValue* object_header = Add<HInnerAllocatedObject>(target, object_offset);
10040 AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset));
10041 Handle<Map> boilerplate_object_map(boilerplate_object->map()); 8659 Handle<Map> boilerplate_object_map(boilerplate_object->map());
10042 AddStoreMapConstant(object_header, boilerplate_object_map); 8660 AddStoreMapConstant(object_header, boilerplate_object_map);
10043 8661
10044 HInstruction* elements; 8662 HInstruction* elements;
10045 if (elements_size == 0) { 8663 if (elements_size == 0) {
10046 Handle<Object> elements_field = 8664 Handle<Object> elements_field =
10047 Handle<Object>(boilerplate_object->elements(), isolate()); 8665 Handle<Object>(boilerplate_object->elements(), isolate());
10048 elements = AddInstruction(new(zone) HConstant(elements_field)); 8666 elements = Add<HConstant>(elements_field);
10049 } else { 8667 } else {
10050 if (data_target != NULL && boilerplate_object->HasFastDoubleElements()) { 8668 if (data_target != NULL && boilerplate_object->HasFastDoubleElements()) {
10051 elements = AddInstruction(new(zone) HInnerAllocatedObject( 8669 elements = Add<HInnerAllocatedObject>(data_target, elements_offset);
10052 data_target, elements_offset));
10053 } else { 8670 } else {
10054 elements = AddInstruction(new(zone) HInnerAllocatedObject( 8671 elements = Add<HInnerAllocatedObject>(target, elements_offset);
10055 target, elements_offset));
10056 } 8672 }
10057 result = elements; 8673 result = elements;
10058 } 8674 }
10059 AddStore(object_header, HObjectAccess::ForElementsPointer(), elements); 8675 AddStore(object_header, HObjectAccess::ForElementsPointer(), elements);
10060 8676
10061 Handle<Object> properties_field = 8677 Handle<Object> properties_field =
10062 Handle<Object>(boilerplate_object->properties(), isolate()); 8678 Handle<Object>(boilerplate_object->properties(), isolate());
10063 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); 8679 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array());
10064 HInstruction* properties = AddInstruction(new(zone) HConstant( 8680 HInstruction* properties = Add<HConstant>(properties_field);
10065 properties_field));
10066 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); 8681 HObjectAccess access = HObjectAccess::ForPropertiesPointer();
10067 AddStore(object_header, access, properties); 8682 AddStore(object_header, access, properties);
10068 8683
10069 if (boilerplate_object->IsJSArray()) { 8684 if (boilerplate_object->IsJSArray()) {
10070 Handle<JSArray> boilerplate_array = 8685 Handle<JSArray> boilerplate_array =
10071 Handle<JSArray>::cast(boilerplate_object); 8686 Handle<JSArray>::cast(boilerplate_object);
10072 Handle<Object> length_field = 8687 Handle<Object> length_field =
10073 Handle<Object>(boilerplate_array->length(), isolate()); 8688 Handle<Object>(boilerplate_array->length(), isolate());
10074 HInstruction* length = AddInstruction(new(zone) HConstant(length_field)); 8689 HInstruction* length = Add<HConstant>(length_field);
10075 8690
10076 ASSERT(boilerplate_array->length()->IsSmi()); 8691 ASSERT(boilerplate_array->length()->IsSmi());
10077 Representation representation = 8692 Representation representation =
10078 IsFastElementsKind(boilerplate_array->GetElementsKind()) 8693 IsFastElementsKind(boilerplate_array->GetElementsKind())
10079 ? Representation::Smi() : Representation::Tagged(); 8694 ? Representation::Smi() : Representation::Tagged();
10080 AddStore(object_header, HObjectAccess::ForArrayLength(), 8695 AddStore(object_header, HObjectAccess::ForArrayLength(),
10081 length, representation); 8696 length, representation);
10082 } 8697 }
10083 8698
10084 return result; 8699 return result;
10085 } 8700 }
10086 8701
10087 8702
10088 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( 8703 void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
10089 Handle<JSObject> boilerplate_object, 8704 Handle<JSObject> boilerplate_object,
10090 Handle<JSObject> original_boilerplate_object, 8705 Handle<JSObject> original_boilerplate_object,
10091 HValue* object_properties, 8706 HValue* object_properties,
10092 HInstruction* target, 8707 HInstruction* target,
10093 int* offset, 8708 int* offset,
10094 HInstruction* data_target, 8709 HInstruction* data_target,
10095 int* data_offset) { 8710 int* data_offset) {
10096 Zone* zone = this->zone();
10097 Handle<DescriptorArray> descriptors( 8711 Handle<DescriptorArray> descriptors(
10098 boilerplate_object->map()->instance_descriptors()); 8712 boilerplate_object->map()->instance_descriptors());
10099 int limit = boilerplate_object->map()->NumberOfOwnDescriptors(); 8713 int limit = boilerplate_object->map()->NumberOfOwnDescriptors();
10100 8714
10101 int copied_fields = 0; 8715 int copied_fields = 0;
10102 for (int i = 0; i < limit; i++) { 8716 for (int i = 0; i < limit; i++) {
10103 PropertyDetails details = descriptors->GetDetails(i); 8717 PropertyDetails details = descriptors->GetDetails(i);
10104 if (details.type() != FIELD) continue; 8718 if (details.type() != FIELD) continue;
10105 copied_fields++; 8719 copied_fields++;
10106 int index = descriptors->GetFieldIndex(i); 8720 int index = descriptors->GetFieldIndex(i);
10107 int property_offset = boilerplate_object->GetInObjectPropertyOffset(index); 8721 int property_offset = boilerplate_object->GetInObjectPropertyOffset(index);
10108 Handle<Name> name(descriptors->GetKey(i)); 8722 Handle<Name> name(descriptors->GetKey(i));
10109 Handle<Object> value = 8723 Handle<Object> value =
10110 Handle<Object>(boilerplate_object->InObjectPropertyAt(index), 8724 Handle<Object>(boilerplate_object->InObjectPropertyAt(index),
10111 isolate()); 8725 isolate());
10112 8726
10113 // The access for the store depends on the type of the boilerplate. 8727 // The access for the store depends on the type of the boilerplate.
10114 HObjectAccess access = boilerplate_object->IsJSArray() ? 8728 HObjectAccess access = boilerplate_object->IsJSArray() ?
10115 HObjectAccess::ForJSArrayOffset(property_offset) : 8729 HObjectAccess::ForJSArrayOffset(property_offset) :
10116 HObjectAccess::ForJSObjectOffset(property_offset); 8730 HObjectAccess::ForJSObjectOffset(property_offset);
10117 8731
10118 if (value->IsJSObject()) { 8732 if (value->IsJSObject()) {
10119 Handle<JSObject> value_object = Handle<JSObject>::cast(value); 8733 Handle<JSObject> value_object = Handle<JSObject>::cast(value);
10120 Handle<JSObject> original_value_object = Handle<JSObject>::cast( 8734 Handle<JSObject> original_value_object = Handle<JSObject>::cast(
10121 Handle<Object>(original_boilerplate_object->InObjectPropertyAt(index), 8735 Handle<Object>(original_boilerplate_object->InObjectPropertyAt(index),
10122 isolate())); 8736 isolate()));
10123 HInstruction* value_instruction = 8737 HInstruction* value_instruction = Add<HInnerAllocatedObject>(target,
10124 AddInstruction(new(zone) HInnerAllocatedObject(target, *offset)); 8738 *offset);
10125 8739
10126 AddStore(object_properties, access, value_instruction); 8740 AddStore(object_properties, access, value_instruction);
10127 8741 BuildEmitDeepCopy(value_object, original_value_object,
10128 BuildEmitDeepCopy(value_object, original_value_object, target, 8742 Handle<Object>::null(), target,
10129 offset, data_target, data_offset, DONT_TRACK_ALLOCATION_SITE); 8743 offset, data_target, data_offset,
8744 DONT_TRACK_ALLOCATION_SITE);
10130 } else { 8745 } else {
10131 Representation representation = details.representation(); 8746 Representation representation = details.representation();
10132 HInstruction* value_instruction = 8747 HInstruction* value_instruction = Add<HConstant>(value);
10133 AddInstruction(new(zone) HConstant(value));
10134 8748
10135 if (representation.IsDouble()) { 8749 if (representation.IsDouble()) {
10136 // Allocate a HeapNumber box and store the value into it. 8750 // Allocate a HeapNumber box and store the value into it.
10137 HInstruction* double_box; 8751 HInstruction* double_box;
10138 if (data_target != NULL) { 8752 if (data_target != NULL) {
10139 double_box = AddInstruction(new(zone) HInnerAllocatedObject( 8753 double_box = Add<HInnerAllocatedObject>(data_target, *data_offset);
10140 data_target, *data_offset));
10141 *data_offset += HeapNumber::kSize; 8754 *data_offset += HeapNumber::kSize;
10142 } else { 8755 } else {
10143 double_box = AddInstruction(new(zone) HInnerAllocatedObject( 8756 double_box = Add<HInnerAllocatedObject>(target, *offset);
10144 target, *offset));
10145 *offset += HeapNumber::kSize; 8757 *offset += HeapNumber::kSize;
10146 } 8758 }
10147 AddStoreMapConstant(double_box, 8759 AddStoreMapConstant(double_box,
10148 isolate()->factory()->heap_number_map()); 8760 isolate()->factory()->heap_number_map());
10149 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), 8761 AddStore(double_box, HObjectAccess::ForHeapNumberValue(),
10150 value_instruction, Representation::Double()); 8762 value_instruction, Representation::Double());
10151 value_instruction = double_box; 8763 value_instruction = double_box;
10152 } 8764 }
10153 8765
10154 AddStore(object_properties, access, value_instruction); 8766 AddStore(object_properties, access, value_instruction);
10155 } 8767 }
10156 } 8768 }
10157 8769
10158 int inobject_properties = boilerplate_object->map()->inobject_properties(); 8770 int inobject_properties = boilerplate_object->map()->inobject_properties();
10159 HInstruction* value_instruction = AddInstruction(new(zone) 8771 HInstruction* value_instruction =
10160 HConstant(isolate()->factory()->one_pointer_filler_map())); 8772 Add<HConstant>(isolate()->factory()->one_pointer_filler_map());
10161 for (int i = copied_fields; i < inobject_properties; i++) { 8773 for (int i = copied_fields; i < inobject_properties; i++) {
10162 ASSERT(boilerplate_object->IsJSObject()); 8774 ASSERT(boilerplate_object->IsJSObject());
10163 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); 8775 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i);
10164 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); 8776 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset);
10165 AddStore(object_properties, access, value_instruction); 8777 AddStore(object_properties, access, value_instruction);
10166 } 8778 }
10167 } 8779 }
10168 8780
10169 8781
10170 void HOptimizedGraphBuilder::BuildEmitElements( 8782 void HOptimizedGraphBuilder::BuildEmitElements(
10171 Handle<FixedArrayBase> elements, 8783 Handle<FixedArrayBase> elements,
10172 Handle<FixedArrayBase> original_elements, 8784 Handle<FixedArrayBase> original_elements,
10173 ElementsKind kind, 8785 ElementsKind kind,
10174 HValue* object_elements, 8786 HValue* object_elements,
10175 HInstruction* target, 8787 HInstruction* target,
10176 int* offset, 8788 int* offset,
10177 HInstruction* data_target, 8789 HInstruction* data_target,
10178 int* data_offset) { 8790 int* data_offset) {
10179 Zone* zone = this->zone();
10180
10181 int elements_length = elements->length(); 8791 int elements_length = elements->length();
10182 HValue* object_elements_length = 8792 HValue* object_elements_length = Add<HConstant>(elements_length);
10183 AddInstruction(new(zone) HConstant(elements_length));
10184 8793
10185 BuildInitializeElementsHeader(object_elements, kind, object_elements_length); 8794 BuildInitializeElementsHeader(object_elements, kind, object_elements_length);
10186 8795
10187 // Copy elements backing store content. 8796 // Copy elements backing store content.
10188 if (elements->IsFixedDoubleArray()) { 8797 if (elements->IsFixedDoubleArray()) {
10189 BuildEmitFixedDoubleArray(elements, kind, object_elements); 8798 BuildEmitFixedDoubleArray(elements, kind, object_elements);
10190 } else if (elements->IsFixedArray()) { 8799 } else if (elements->IsFixedArray()) {
10191 BuildEmitFixedArray(elements, original_elements, kind, object_elements, 8800 BuildEmitFixedArray(elements, original_elements, kind, object_elements,
10192 target, offset, data_target, data_offset); 8801 target, offset, data_target, data_offset);
10193 } else { 8802 } else {
10194 UNREACHABLE(); 8803 UNREACHABLE();
10195 } 8804 }
10196 } 8805 }
10197 8806
10198 8807
10199 void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray( 8808 void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray(
10200 Handle<FixedArrayBase> elements, 8809 Handle<FixedArrayBase> elements,
10201 ElementsKind kind, 8810 ElementsKind kind,
10202 HValue* object_elements) { 8811 HValue* object_elements) {
10203 Zone* zone = this->zone(); 8812 HInstruction* boilerplate_elements = Add<HConstant>(elements);
10204 HInstruction* boilerplate_elements =
10205 AddInstruction(new(zone) HConstant(elements));
10206 int elements_length = elements->length(); 8813 int elements_length = elements->length();
10207 for (int i = 0; i < elements_length; i++) { 8814 for (int i = 0; i < elements_length; i++) {
10208 HValue* key_constant = AddInstruction(new(zone) HConstant(i)); 8815 HValue* key_constant = Add<HConstant>(i);
10209 HInstruction* value_instruction = 8816 HInstruction* value_instruction =
10210 AddInstruction(new(zone) HLoadKeyed( 8817 Add<HLoadKeyed>(boilerplate_elements, key_constant,
10211 boilerplate_elements, key_constant, NULL, kind, ALLOW_RETURN_HOLE)); 8818 static_cast<HValue*>(NULL), kind,
10212 HInstruction* store = AddInstruction(new(zone) HStoreKeyed( 8819 ALLOW_RETURN_HOLE);
10213 object_elements, key_constant, value_instruction, kind)); 8820 HInstruction* store = Add<HStoreKeyed>(object_elements, key_constant,
8821 value_instruction, kind);
10214 store->SetFlag(HValue::kAllowUndefinedAsNaN); 8822 store->SetFlag(HValue::kAllowUndefinedAsNaN);
10215 } 8823 }
10216 } 8824 }
10217 8825
10218 8826
10219 void HOptimizedGraphBuilder::BuildEmitFixedArray( 8827 void HOptimizedGraphBuilder::BuildEmitFixedArray(
10220 Handle<FixedArrayBase> elements, 8828 Handle<FixedArrayBase> elements,
10221 Handle<FixedArrayBase> original_elements, 8829 Handle<FixedArrayBase> original_elements,
10222 ElementsKind kind, 8830 ElementsKind kind,
10223 HValue* object_elements, 8831 HValue* object_elements,
10224 HInstruction* target, 8832 HInstruction* target,
10225 int* offset, 8833 int* offset,
10226 HInstruction* data_target, 8834 HInstruction* data_target,
10227 int* data_offset) { 8835 int* data_offset) {
10228 Zone* zone = this->zone(); 8836 HInstruction* boilerplate_elements = Add<HConstant>(elements);
10229 HInstruction* boilerplate_elements =
10230 AddInstruction(new(zone) HConstant(elements));
10231 int elements_length = elements->length(); 8837 int elements_length = elements->length();
10232 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); 8838 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
10233 Handle<FixedArray> original_fast_elements = 8839 Handle<FixedArray> original_fast_elements =
10234 Handle<FixedArray>::cast(original_elements); 8840 Handle<FixedArray>::cast(original_elements);
10235 for (int i = 0; i < elements_length; i++) { 8841 for (int i = 0; i < elements_length; i++) {
10236 Handle<Object> value(fast_elements->get(i), isolate()); 8842 Handle<Object> value(fast_elements->get(i), isolate());
10237 HValue* key_constant = AddInstruction(new(zone) HConstant(i)); 8843 HValue* key_constant = Add<HConstant>(i);
10238 if (value->IsJSObject()) { 8844 if (value->IsJSObject()) {
10239 Handle<JSObject> value_object = Handle<JSObject>::cast(value); 8845 Handle<JSObject> value_object = Handle<JSObject>::cast(value);
10240 Handle<JSObject> original_value_object = Handle<JSObject>::cast( 8846 Handle<JSObject> original_value_object = Handle<JSObject>::cast(
10241 Handle<Object>(original_fast_elements->get(i), isolate())); 8847 Handle<Object>(original_fast_elements->get(i), isolate()));
10242 HInstruction* value_instruction = 8848 HInstruction* value_instruction = Add<HInnerAllocatedObject>(target,
10243 AddInstruction(new(zone) HInnerAllocatedObject(target, *offset)); 8849 *offset);
10244 AddInstruction(new(zone) HStoreKeyed( 8850 Add<HStoreKeyed>(object_elements, key_constant, value_instruction, kind);
10245 object_elements, key_constant, value_instruction, kind)); 8851 BuildEmitDeepCopy(value_object, original_value_object,
10246 BuildEmitDeepCopy(value_object, original_value_object, target, 8852 Handle<Object>::null(), target,
10247 offset, data_target, data_offset, DONT_TRACK_ALLOCATION_SITE); 8853 offset, data_target, data_offset,
8854 DONT_TRACK_ALLOCATION_SITE);
10248 } else { 8855 } else {
10249 HInstruction* value_instruction = 8856 HInstruction* value_instruction =
10250 AddInstruction(new(zone) HLoadKeyed( 8857 Add<HLoadKeyed>(boilerplate_elements, key_constant,
10251 boilerplate_elements, key_constant, NULL, kind, 8858 static_cast<HValue*>(NULL), kind,
10252 ALLOW_RETURN_HOLE)); 8859 ALLOW_RETURN_HOLE);
10253 AddInstruction(new(zone) HStoreKeyed( 8860 Add<HStoreKeyed>(object_elements, key_constant, value_instruction, kind);
10254 object_elements, key_constant, value_instruction, kind));
10255 } 8861 }
10256 } 8862 }
10257 } 8863 }
10258 8864
8865
10259 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) { 8866 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) {
10260 ASSERT(!HasStackOverflow()); 8867 ASSERT(!HasStackOverflow());
10261 ASSERT(current_block() != NULL); 8868 ASSERT(current_block() != NULL);
10262 ASSERT(current_block()->HasPredecessor()); 8869 ASSERT(current_block()->HasPredecessor());
10263 HInstruction* instr = BuildThisFunction(); 8870 HInstruction* instr = BuildThisFunction();
10264 return ast_context()->ReturnInstruction(instr, expr->id()); 8871 return ast_context()->ReturnInstruction(instr, expr->id());
10265 } 8872 }
10266 8873
10267 8874
10268 void HOptimizedGraphBuilder::VisitDeclarations( 8875 void HOptimizedGraphBuilder::VisitDeclarations(
10269 ZoneList<Declaration*>* declarations) { 8876 ZoneList<Declaration*>* declarations) {
10270 ASSERT(globals_.is_empty()); 8877 ASSERT(globals_.is_empty());
10271 AstVisitor::VisitDeclarations(declarations); 8878 AstVisitor::VisitDeclarations(declarations);
10272 if (!globals_.is_empty()) { 8879 if (!globals_.is_empty()) {
10273 Handle<FixedArray> array = 8880 Handle<FixedArray> array =
10274 isolate()->factory()->NewFixedArray(globals_.length(), TENURED); 8881 isolate()->factory()->NewFixedArray(globals_.length(), TENURED);
10275 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i)); 8882 for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i));
10276 int flags = DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) | 8883 int flags = DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) |
10277 DeclareGlobalsNativeFlag::encode(current_info()->is_native()) | 8884 DeclareGlobalsNativeFlag::encode(current_info()->is_native()) |
10278 DeclareGlobalsLanguageMode::encode(current_info()->language_mode()); 8885 DeclareGlobalsLanguageMode::encode(current_info()->language_mode());
10279 HInstruction* result = new(zone()) HDeclareGlobals( 8886 Add<HDeclareGlobals>(environment()->LookupContext(), array, flags);
10280 environment()->LookupContext(), array, flags);
10281 AddInstruction(result);
10282 globals_.Clear(); 8887 globals_.Clear();
10283 } 8888 }
10284 } 8889 }
10285 8890
10286 8891
10287 void HOptimizedGraphBuilder::VisitVariableDeclaration( 8892 void HOptimizedGraphBuilder::VisitVariableDeclaration(
10288 VariableDeclaration* declaration) { 8893 VariableDeclaration* declaration) {
10289 VariableProxy* proxy = declaration->proxy(); 8894 VariableProxy* proxy = declaration->proxy();
10290 VariableMode mode = declaration->mode(); 8895 VariableMode mode = declaration->mode();
10291 Variable* variable = proxy->var(); 8896 Variable* variable = proxy->var();
10292 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET; 8897 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET;
10293 switch (variable->location()) { 8898 switch (variable->location()) {
10294 case Variable::UNALLOCATED: 8899 case Variable::UNALLOCATED:
10295 globals_.Add(variable->name(), zone()); 8900 globals_.Add(variable->name(), zone());
10296 globals_.Add(variable->binding_needs_init() 8901 globals_.Add(variable->binding_needs_init()
10297 ? isolate()->factory()->the_hole_value() 8902 ? isolate()->factory()->the_hole_value()
10298 : isolate()->factory()->undefined_value(), zone()); 8903 : isolate()->factory()->undefined_value(), zone());
10299 return; 8904 return;
10300 case Variable::PARAMETER: 8905 case Variable::PARAMETER:
10301 case Variable::LOCAL: 8906 case Variable::LOCAL:
10302 if (hole_init) { 8907 if (hole_init) {
10303 HValue* value = graph()->GetConstantHole(); 8908 HValue* value = graph()->GetConstantHole();
10304 environment()->Bind(variable, value); 8909 environment()->Bind(variable, value);
10305 } 8910 }
10306 break; 8911 break;
10307 case Variable::CONTEXT: 8912 case Variable::CONTEXT:
10308 if (hole_init) { 8913 if (hole_init) {
10309 HValue* value = graph()->GetConstantHole(); 8914 HValue* value = graph()->GetConstantHole();
10310 HValue* context = environment()->LookupContext(); 8915 HValue* context = environment()->LookupContext();
10311 HStoreContextSlot* store = new(zone()) HStoreContextSlot( 8916 HStoreContextSlot* store = Add<HStoreContextSlot>(
10312 context, variable->index(), HStoreContextSlot::kNoCheck, value); 8917 context, variable->index(), HStoreContextSlot::kNoCheck, value);
10313 AddInstruction(store);
10314 if (store->HasObservableSideEffects()) { 8918 if (store->HasObservableSideEffects()) {
10315 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); 8919 AddSimulate(proxy->id(), REMOVABLE_SIMULATE);
10316 } 8920 }
10317 } 8921 }
10318 break; 8922 break;
10319 case Variable::LOOKUP: 8923 case Variable::LOOKUP:
10320 return Bailout("unsupported lookup slot in declaration"); 8924 return Bailout("unsupported lookup slot in declaration");
10321 } 8925 }
10322 } 8926 }
10323 8927
(...skipping 16 matching lines...) Expand all
10340 case Variable::LOCAL: { 8944 case Variable::LOCAL: {
10341 CHECK_ALIVE(VisitForValue(declaration->fun())); 8945 CHECK_ALIVE(VisitForValue(declaration->fun()));
10342 HValue* value = Pop(); 8946 HValue* value = Pop();
10343 BindIfLive(variable, value); 8947 BindIfLive(variable, value);
10344 break; 8948 break;
10345 } 8949 }
10346 case Variable::CONTEXT: { 8950 case Variable::CONTEXT: {
10347 CHECK_ALIVE(VisitForValue(declaration->fun())); 8951 CHECK_ALIVE(VisitForValue(declaration->fun()));
10348 HValue* value = Pop(); 8952 HValue* value = Pop();
10349 HValue* context = environment()->LookupContext(); 8953 HValue* context = environment()->LookupContext();
10350 HStoreContextSlot* store = new(zone()) HStoreContextSlot( 8954 HStoreContextSlot* store = Add<HStoreContextSlot>(
10351 context, variable->index(), HStoreContextSlot::kNoCheck, value); 8955 context, variable->index(), HStoreContextSlot::kNoCheck, value);
10352 AddInstruction(store);
10353 if (store->HasObservableSideEffects()) { 8956 if (store->HasObservableSideEffects()) {
10354 AddSimulate(proxy->id(), REMOVABLE_SIMULATE); 8957 AddSimulate(proxy->id(), REMOVABLE_SIMULATE);
10355 } 8958 }
10356 break; 8959 break;
10357 } 8960 }
10358 case Variable::LOOKUP: 8961 case Variable::LOOKUP:
10359 return Bailout("unsupported lookup slot in declaration"); 8962 return Bailout("unsupported lookup slot in declaration");
10360 } 8963 }
10361 } 8964 }
10362 8965
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
10514 } 9117 }
10515 9118
10516 9119
10517 // Support for arguments.length and arguments[?]. 9120 // Support for arguments.length and arguments[?].
10518 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { 9121 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
10519 // Our implementation of arguments (based on this stack frame or an 9122 // Our implementation of arguments (based on this stack frame or an
10520 // adapter below it) does not work for inlined functions. This runtime 9123 // adapter below it) does not work for inlined functions. This runtime
10521 // function is blacklisted by AstNode::IsInlineable. 9124 // function is blacklisted by AstNode::IsInlineable.
10522 ASSERT(function_state()->outer() == NULL); 9125 ASSERT(function_state()->outer() == NULL);
10523 ASSERT(call->arguments()->length() == 0); 9126 ASSERT(call->arguments()->length() == 0);
10524 HInstruction* elements = AddInstruction( 9127 HInstruction* elements = Add<HArgumentsElements>(false);
10525 new(zone()) HArgumentsElements(false));
10526 HArgumentsLength* result = new(zone()) HArgumentsLength(elements); 9128 HArgumentsLength* result = new(zone()) HArgumentsLength(elements);
10527 return ast_context()->ReturnInstruction(result, call->id()); 9129 return ast_context()->ReturnInstruction(result, call->id());
10528 } 9130 }
10529 9131
10530 9132
10531 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) { 9133 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) {
10532 // Our implementation of arguments (based on this stack frame or an 9134 // Our implementation of arguments (based on this stack frame or an
10533 // adapter below it) does not work for inlined functions. This runtime 9135 // adapter below it) does not work for inlined functions. This runtime
10534 // function is blacklisted by AstNode::IsInlineable. 9136 // function is blacklisted by AstNode::IsInlineable.
10535 ASSERT(function_state()->outer() == NULL); 9137 ASSERT(function_state()->outer() == NULL);
10536 ASSERT(call->arguments()->length() == 1); 9138 ASSERT(call->arguments()->length() == 1);
10537 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 9139 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
10538 HValue* index = Pop(); 9140 HValue* index = Pop();
10539 HInstruction* elements = AddInstruction( 9141 HInstruction* elements = Add<HArgumentsElements>(false);
10540 new(zone()) HArgumentsElements(false)); 9142 HInstruction* length = Add<HArgumentsLength>(elements);
10541 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); 9143 HInstruction* checked_index = Add<HBoundsCheck>(index, length);
10542 HInstruction* checked_index = AddBoundsCheck(index, length);
10543 HAccessArgumentsAt* result = 9144 HAccessArgumentsAt* result =
10544 new(zone()) HAccessArgumentsAt(elements, length, checked_index); 9145 new(zone()) HAccessArgumentsAt(elements, length, checked_index);
10545 return ast_context()->ReturnInstruction(result, call->id()); 9146 return ast_context()->ReturnInstruction(result, call->id());
10546 } 9147 }
10547 9148
10548 9149
10549 // Support for accessing the class and value fields of an object. 9150 // Support for accessing the class and value fields of an object.
10550 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) { 9151 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) {
10551 // The special form detected by IsClassOfTest is detected before we get here 9152 // The special form detected by IsClassOfTest is detected before we get here
10552 // and does not cause a bailout. 9153 // and does not cause a bailout.
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
10696 9297
10697 void HOptimizedGraphBuilder::GenerateLog(CallRuntime* call) { 9298 void HOptimizedGraphBuilder::GenerateLog(CallRuntime* call) {
10698 // %_Log is ignored in optimized code. 9299 // %_Log is ignored in optimized code.
10699 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); 9300 return ast_context()->ReturnValue(graph()->GetConstantUndefined());
10700 } 9301 }
10701 9302
10702 9303
10703 // Fast support for Math.random(). 9304 // Fast support for Math.random().
10704 void HOptimizedGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { 9305 void HOptimizedGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) {
10705 HValue* context = environment()->LookupContext(); 9306 HValue* context = environment()->LookupContext();
10706 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 9307 HGlobalObject* global_object = Add<HGlobalObject>(context);
10707 AddInstruction(global_object);
10708 HRandom* result = new(zone()) HRandom(global_object); 9308 HRandom* result = new(zone()) HRandom(global_object);
10709 return ast_context()->ReturnInstruction(result, call->id()); 9309 return ast_context()->ReturnInstruction(result, call->id());
10710 } 9310 }
10711 9311
10712 9312
10713 // Fast support for StringAdd. 9313 // Fast support for StringAdd.
10714 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { 9314 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) {
10715 ASSERT_EQ(2, call->arguments()->length()); 9315 ASSERT_EQ(2, call->arguments()->length());
10716 CHECK_ALIVE(VisitArgumentList(call->arguments())); 9316 CHECK_ALIVE(VisitArgumentList(call->arguments()));
10717 HValue* context = environment()->LookupContext(); 9317 HValue* context = environment()->LookupContext();
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
10803 HHasInstanceTypeAndBranch* typecheck = 9403 HHasInstanceTypeAndBranch* typecheck =
10804 new(zone()) HHasInstanceTypeAndBranch(function, JS_FUNCTION_TYPE); 9404 new(zone()) HHasInstanceTypeAndBranch(function, JS_FUNCTION_TYPE);
10805 HBasicBlock* if_jsfunction = graph()->CreateBasicBlock(); 9405 HBasicBlock* if_jsfunction = graph()->CreateBasicBlock();
10806 HBasicBlock* if_nonfunction = graph()->CreateBasicBlock(); 9406 HBasicBlock* if_nonfunction = graph()->CreateBasicBlock();
10807 HBasicBlock* join = graph()->CreateBasicBlock(); 9407 HBasicBlock* join = graph()->CreateBasicBlock();
10808 typecheck->SetSuccessorAt(0, if_jsfunction); 9408 typecheck->SetSuccessorAt(0, if_jsfunction);
10809 typecheck->SetSuccessorAt(1, if_nonfunction); 9409 typecheck->SetSuccessorAt(1, if_nonfunction);
10810 current_block()->Finish(typecheck); 9410 current_block()->Finish(typecheck);
10811 9411
10812 set_current_block(if_jsfunction); 9412 set_current_block(if_jsfunction);
10813 HInstruction* invoke_result = AddInstruction( 9413 HInstruction* invoke_result =
10814 new(zone()) HInvokeFunction(context, function, arg_count)); 9414 Add<HInvokeFunction>(context, function, arg_count);
10815 Drop(arg_count); 9415 Drop(arg_count);
10816 Push(invoke_result); 9416 Push(invoke_result);
10817 if_jsfunction->Goto(join); 9417 if_jsfunction->Goto(join);
10818 9418
10819 set_current_block(if_nonfunction); 9419 set_current_block(if_nonfunction);
10820 HInstruction* call_result = AddInstruction( 9420 HInstruction* call_result = Add<HCallFunction>(context, function, arg_count);
10821 new(zone()) HCallFunction(context, function, arg_count));
10822 Drop(arg_count); 9421 Drop(arg_count);
10823 Push(call_result); 9422 Push(call_result);
10824 if_nonfunction->Goto(join); 9423 if_nonfunction->Goto(join);
10825 9424
10826 set_current_block(join); 9425 set_current_block(join);
10827 join->SetJoinId(call->id()); 9426 join->SetJoinId(call->id());
10828 return ast_context()->ReturnValue(Pop()); 9427 return ast_context()->ReturnValue(Pop());
10829 } 9428 }
10830 9429
10831 9430
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
10924 void HOptimizedGraphBuilder::GenerateGeneratorNext(CallRuntime* call) { 9523 void HOptimizedGraphBuilder::GenerateGeneratorNext(CallRuntime* call) {
10925 return Bailout("inlined runtime function: GeneratorNext"); 9524 return Bailout("inlined runtime function: GeneratorNext");
10926 } 9525 }
10927 9526
10928 9527
10929 void HOptimizedGraphBuilder::GenerateGeneratorThrow(CallRuntime* call) { 9528 void HOptimizedGraphBuilder::GenerateGeneratorThrow(CallRuntime* call) {
10930 return Bailout("inlined runtime function: GeneratorThrow"); 9529 return Bailout("inlined runtime function: GeneratorThrow");
10931 } 9530 }
10932 9531
10933 9532
9533 void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode(
9534 CallRuntime* call) {
9535 AddInstruction(new(zone()) HDebugBreak());
9536 return ast_context()->ReturnValue(graph()->GetConstant0());
9537 }
9538
9539
10934 #undef CHECK_BAILOUT 9540 #undef CHECK_BAILOUT
10935 #undef CHECK_ALIVE 9541 #undef CHECK_ALIVE
10936 9542
10937 9543
10938 HEnvironment::HEnvironment(HEnvironment* outer, 9544 HEnvironment::HEnvironment(HEnvironment* outer,
10939 Scope* scope, 9545 Scope* scope,
10940 Handle<JSFunction> closure, 9546 Handle<JSFunction> closure,
10941 Zone* zone) 9547 Zone* zone)
10942 : closure_(closure), 9548 : closure_(closure),
10943 values_(0, zone), 9549 values_(0, zone),
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after
11334 trace_.Add("%d ", phi->merged_index()); 9940 trace_.Add("%d ", phi->merged_index());
11335 phi->PrintNameTo(&trace_); 9941 phi->PrintNameTo(&trace_);
11336 trace_.Add(" "); 9942 trace_.Add(" ");
11337 phi->PrintTo(&trace_); 9943 phi->PrintTo(&trace_);
11338 trace_.Add("\n"); 9944 trace_.Add("\n");
11339 } 9945 }
11340 } 9946 }
11341 9947
11342 { 9948 {
11343 Tag HIR_tag(this, "HIR"); 9949 Tag HIR_tag(this, "HIR");
11344 HInstruction* instruction = current->first(); 9950 for (HInstructionIterator it(current); !it.Done(); it.Advance()) {
11345 while (instruction != NULL) { 9951 HInstruction* instruction = it.Current();
11346 int bci = 0; 9952 int bci = 0;
11347 int uses = instruction->UseCount(); 9953 int uses = instruction->UseCount();
11348 PrintIndent(); 9954 PrintIndent();
11349 trace_.Add("%d %d ", bci, uses); 9955 trace_.Add("%d %d ", bci, uses);
11350 instruction->PrintNameTo(&trace_); 9956 instruction->PrintNameTo(&trace_);
11351 trace_.Add(" "); 9957 trace_.Add(" ");
11352 instruction->PrintTo(&trace_); 9958 instruction->PrintTo(&trace_);
11353 trace_.Add(" <|@\n"); 9959 trace_.Add(" <|@\n");
11354 instruction = instruction->next();
11355 } 9960 }
11356 } 9961 }
11357 9962
11358 9963
11359 if (chunk != NULL) { 9964 if (chunk != NULL) {
11360 Tag LIR_tag(this, "LIR"); 9965 Tag LIR_tag(this, "LIR");
11361 int first_index = current->first_instruction_index(); 9966 int first_index = current->first_instruction_index();
11362 int last_index = current->last_instruction_index(); 9967 int last_index = current->last_instruction_index();
11363 if (first_index != -1 && last_index != -1) { 9968 if (first_index != -1 && last_index != -1) {
11364 const ZoneList<LInstruction*>* instructions = chunk->instructions(); 9969 const ZoneList<LInstruction*>* instructions = chunk->instructions();
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
11540 if (ShouldProduceTraceOutput()) { 10145 if (ShouldProduceTraceOutput()) {
11541 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 10146 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
11542 } 10147 }
11543 10148
11544 #ifdef DEBUG 10149 #ifdef DEBUG
11545 graph_->Verify(false); // No full verify. 10150 graph_->Verify(false); // No full verify.
11546 #endif 10151 #endif
11547 } 10152 }
11548 10153
11549 } } // namespace v8::internal 10154 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-bce.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698