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

Side by Side Diff: src/hydrogen.cc

Issue 7535004: Merge bleeding edge up to 8774 into the GC branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 4 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-instructions.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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after
729 order->Contains(block->end()->SecondSuccessor()) || 729 order->Contains(block->end()->SecondSuccessor()) ||
730 block->end()->SecondSuccessor()->IsLoopHeader()); 730 block->end()->SecondSuccessor()->IsLoopHeader());
731 order->Add(block); 731 order->Add(block);
732 } 732 }
733 733
734 734
735 void HGraph::AssignDominators() { 735 void HGraph::AssignDominators() {
736 HPhase phase("Assign dominators", this); 736 HPhase phase("Assign dominators", this);
737 for (int i = 0; i < blocks_.length(); ++i) { 737 for (int i = 0; i < blocks_.length(); ++i) {
738 if (blocks_[i]->IsLoopHeader()) { 738 if (blocks_[i]->IsLoopHeader()) {
739 // Only the first predecessor of a loop header is from outside the loop.
740 // All others are back edges, and thus cannot dominate the loop header.
739 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->first()); 741 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->first());
740 } else { 742 } else {
741 for (int j = 0; j < blocks_[i]->predecessors()->length(); ++j) { 743 for (int j = 0; j < blocks_[i]->predecessors()->length(); ++j) {
742 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j)); 744 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j));
743 } 745 }
744 } 746 }
745 } 747 }
748 }
746 749
747 // Propagate flag marking blocks containing unconditional deoptimize. 750 // Mark all blocks that are dominated by an unconditional soft deoptimize to
751 // prevent code motion across those blocks.
752 void HGraph::PropagateDeoptimizingMark() {
753 HPhase phase("Propagate deoptimizing mark", this);
748 MarkAsDeoptimizingRecursively(entry_block()); 754 MarkAsDeoptimizingRecursively(entry_block());
749 } 755 }
750 756
751
752 // Mark all blocks that are dominated by an unconditional deoptimize.
753 void HGraph::MarkAsDeoptimizingRecursively(HBasicBlock* block) { 757 void HGraph::MarkAsDeoptimizingRecursively(HBasicBlock* block) {
754 for (int i = 0; i < block->dominated_blocks()->length(); ++i) { 758 for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
755 HBasicBlock* dominated = block->dominated_blocks()->at(i); 759 HBasicBlock* dominated = block->dominated_blocks()->at(i);
756 if (block->IsDeoptimizing()) dominated->MarkAsDeoptimizing(); 760 if (block->IsDeoptimizing()) dominated->MarkAsDeoptimizing();
757 MarkAsDeoptimizingRecursively(dominated); 761 MarkAsDeoptimizingRecursively(dominated);
758 } 762 }
759 } 763 }
760 764
761 void HGraph::EliminateRedundantPhis() { 765 void HGraph::EliminateRedundantPhis() {
762 HPhase phase("Redundant phi elimination", this); 766 HPhase phase("Redundant phi elimination", this);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
829 HPhi* phi = phi_list[i]; 833 HPhi* phi = phi_list[i];
830 if (!phi->is_live()) { 834 if (!phi->is_live()) {
831 HBasicBlock* block = phi->block(); 835 HBasicBlock* block = phi->block();
832 block->RemovePhi(phi); 836 block->RemovePhi(phi);
833 block->RecordDeletedPhi(phi->merged_index()); 837 block->RecordDeletedPhi(phi->merged_index());
834 } 838 }
835 } 839 }
836 } 840 }
837 841
838 842
843 bool HGraph::CheckPhis() {
844 int block_count = blocks_.length();
845 for (int i = 0; i < block_count; ++i) {
846 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
847 HPhi* phi = blocks_[i]->phis()->at(j);
848 // We don't support phi uses of arguments for now.
849 if (phi->CheckFlag(HValue::kIsArguments)) return false;
850 }
851 }
852 return true;
853 }
854
855
839 bool HGraph::CollectPhis() { 856 bool HGraph::CollectPhis() {
840 int block_count = blocks_.length(); 857 int block_count = blocks_.length();
841 phi_list_ = new ZoneList<HPhi*>(block_count); 858 phi_list_ = new ZoneList<HPhi*>(block_count);
842 for (int i = 0; i < block_count; ++i) { 859 for (int i = 0; i < block_count; ++i) {
843 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) { 860 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
844 HPhi* phi = blocks_[i]->phis()->at(j); 861 HPhi* phi = blocks_[i]->phis()->at(j);
845 phi_list_->Add(phi); 862 phi_list_->Add(phi);
846 // We don't support phi uses of arguments for now.
847 if (phi->CheckFlag(HValue::kIsArguments)) return false;
848 // Check for the hole value (from an uninitialized const). 863 // Check for the hole value (from an uninitialized const).
849 for (int k = 0; k < phi->OperandCount(); k++) { 864 for (int k = 0; k < phi->OperandCount(); k++) {
850 if (phi->OperandAt(k) == GetConstantHole()) return false; 865 if (phi->OperandAt(k) == GetConstantHole()) return false;
851 } 866 }
852 } 867 }
853 } 868 }
854 return true; 869 return true;
855 } 870 }
856 871
857 872
(...skipping 801 matching lines...) Expand 10 before | Expand all | Expand 10 after
1659 // indirectly through a transitive closure of the def-use relation. 1674 // indirectly through a transitive closure of the def-use relation.
1660 bool change = true; 1675 bool change = true;
1661 while (change) { 1676 while (change) {
1662 change = false; 1677 change = false;
1663 for (int i = 0; i < phi_count; ++i) { 1678 for (int i = 0; i < phi_count; ++i) {
1664 HPhi* phi = phi_list->at(i); 1679 HPhi* phi = phi_list->at(i);
1665 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { 1680 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
1666 HValue* use = it.value(); 1681 HValue* use = it.value();
1667 if (use->IsPhi()) { 1682 if (use->IsPhi()) {
1668 int id = HPhi::cast(use)->phi_id(); 1683 int id = HPhi::cast(use)->phi_id();
1669 change = change || 1684 if (connected_phis[i]->UnionIsChanged(*connected_phis[id]))
1670 connected_phis[i]->UnionIsChanged(*connected_phis[id]); 1685 change = true;
1671 } 1686 }
1672 } 1687 }
1673 } 1688 }
1674 } 1689 }
1675 1690
1676 // (3) Sum up the non-phi use counts of all connected phis. Don't include 1691 // (3) Sum up the non-phi use counts of all connected phis. Don't include
1677 // the non-phi uses of the phi itself. 1692 // the non-phi uses of the phi itself.
1678 for (int i = 0; i < phi_count; ++i) { 1693 for (int i = 0; i < phi_count; ++i) {
1679 HPhi* phi = phi_list->at(i); 1694 HPhi* phi = phi_list->at(i);
1680 for (BitVector::Iterator it(connected_phis.at(i)); 1695 for (BitVector::Iterator it(connected_phis.at(i));
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after
2151 // We expect the graph to be in edge-split form: there is no edge that 2166 // We expect the graph to be in edge-split form: there is no edge that
2152 // connects a branch node to a join node. We conservatively ensure that 2167 // connects a branch node to a join node. We conservatively ensure that
2153 // property by always adding an empty block on the outgoing edges of this 2168 // property by always adding an empty block on the outgoing edges of this
2154 // branch. 2169 // branch.
2155 HGraphBuilder* builder = owner(); 2170 HGraphBuilder* builder = owner();
2156 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { 2171 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
2157 builder->Bailout("arguments object value in a test context"); 2172 builder->Bailout("arguments object value in a test context");
2158 } 2173 }
2159 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); 2174 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
2160 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); 2175 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
2161 HBranch* test = new(zone()) HBranch(value, empty_true, empty_false); 2176 unsigned test_id = condition()->test_id();
2177 ToBooleanStub::Types expected(builder->oracle()->ToBooleanTypes(test_id));
2178 HBranch* test = new(zone()) HBranch(value, empty_true, empty_false, expected);
2162 builder->current_block()->Finish(test); 2179 builder->current_block()->Finish(test);
2163 2180
2164 empty_true->Goto(if_true()); 2181 empty_true->Goto(if_true());
2165 empty_false->Goto(if_false()); 2182 empty_false->Goto(if_false());
2166 builder->set_current_block(NULL); 2183 builder->set_current_block(NULL);
2167 } 2184 }
2168 2185
2169 2186
2170 // HGraphBuilder infrastructure for bailing out and checking bailouts. 2187 // HGraphBuilder infrastructure for bailing out and checking bailouts.
2171 #define CHECK_BAILOUT(call) \ 2188 #define CHECK_BAILOUT(call) \
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
2286 2303
2287 if (current_block() != NULL) { 2304 if (current_block() != NULL) {
2288 HReturn* instr = new(zone()) HReturn(graph()->GetConstantUndefined()); 2305 HReturn* instr = new(zone()) HReturn(graph()->GetConstantUndefined());
2289 current_block()->FinishExit(instr); 2306 current_block()->FinishExit(instr);
2290 set_current_block(NULL); 2307 set_current_block(NULL);
2291 } 2308 }
2292 } 2309 }
2293 2310
2294 graph()->OrderBlocks(); 2311 graph()->OrderBlocks();
2295 graph()->AssignDominators(); 2312 graph()->AssignDominators();
2313 graph()->PropagateDeoptimizingMark();
2314 if (!graph()->CheckPhis()) {
2315 Bailout("Unsupported phi use of arguments object");
2316 return NULL;
2317 }
2296 graph()->EliminateRedundantPhis(); 2318 graph()->EliminateRedundantPhis();
2297 if (FLAG_eliminate_dead_phis) graph()->EliminateUnreachablePhis(); 2319 if (FLAG_eliminate_dead_phis) graph()->EliminateUnreachablePhis();
2298 if (!graph()->CollectPhis()) { 2320 if (!graph()->CollectPhis()) {
2299 Bailout("Unsupported phi-use"); 2321 Bailout("Unsupported phi use of uninitialized constant");
2300 return NULL; 2322 return NULL;
2301 } 2323 }
2302 2324
2303 HInferRepresentation rep(graph()); 2325 HInferRepresentation rep(graph());
2304 rep.Analyze(); 2326 rep.Analyze();
2305 2327
2306 if (FLAG_use_range) { 2328 if (FLAG_use_range) {
2307 HRangeAnalysis rangeAnalysis(graph()); 2329 HRangeAnalysis rangeAnalysis(graph());
2308 rangeAnalysis.Analyze(); 2330 rangeAnalysis.Analyze();
2309 } 2331 }
(...skipping 957 matching lines...) Expand 10 before | Expand all | Expand 10 after
3267 // If the subexpression is a literal or a simple materialized literal it 3289 // If the subexpression is a literal or a simple materialized literal it
3268 // is already set in the cloned array. 3290 // is already set in the cloned array.
3269 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 3291 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
3270 3292
3271 CHECK_ALIVE(VisitForValue(subexpr)); 3293 CHECK_ALIVE(VisitForValue(subexpr));
3272 HValue* value = Pop(); 3294 HValue* value = Pop();
3273 if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal"); 3295 if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal");
3274 3296
3275 // Load the elements array before the first store. 3297 // Load the elements array before the first store.
3276 if (elements == NULL) { 3298 if (elements == NULL) {
3277 elements = new(zone()) HLoadElements(literal); 3299 elements = new(zone()) HLoadElements(literal);
3278 AddInstruction(elements); 3300 AddInstruction(elements);
3279 } 3301 }
3280 3302
3281 HValue* key = AddInstruction( 3303 HValue* key = AddInstruction(
3282 new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)), 3304 new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)),
3283 Representation::Integer32())); 3305 Representation::Integer32()));
3284 AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value)); 3306 AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value));
3285 AddSimulate(expr->GetIdForElement(i)); 3307 AddSimulate(expr->GetIdForElement(i));
3286 } 3308 }
3287 return ast_context()->ReturnValue(Pop()); 3309 return ast_context()->ReturnValue(Pop());
3288 } 3310 }
(...skipping 605 matching lines...) Expand 10 before | Expand all | Expand 10 after
3894 } 3916 }
3895 3917
3896 3918
3897 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object, 3919 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object,
3898 HValue* key, 3920 HValue* key,
3899 HValue* val, 3921 HValue* val,
3900 Expression* expr, 3922 Expression* expr,
3901 bool is_store) { 3923 bool is_store) {
3902 ASSERT(expr->IsMonomorphic()); 3924 ASSERT(expr->IsMonomorphic());
3903 Handle<Map> map = expr->GetMonomorphicReceiverType(); 3925 Handle<Map> map = expr->GetMonomorphicReceiverType();
3904 if (!map->has_fast_elements() && !map->has_external_array_elements()) { 3926 if (!map->has_fast_elements() &&
3927 !map->has_fast_double_elements() &&
3928 !map->has_external_array_elements()) {
3905 return is_store ? BuildStoreKeyedGeneric(object, key, val) 3929 return is_store ? BuildStoreKeyedGeneric(object, key, val)
3906 : BuildLoadKeyedGeneric(object, key); 3930 : BuildLoadKeyedGeneric(object, key);
3907 } 3931 }
3908 AddInstruction(new(zone()) HCheckNonSmi(object)); 3932 AddInstruction(new(zone()) HCheckNonSmi(object));
3909 AddInstruction(new(zone()) HCheckMap(object, map)); 3933 HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMap(object, map));
3910 HInstruction* elements = new(zone()) HLoadElements(object); 3934 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object));
3935 bool fast_double_elements = map->has_fast_double_elements();
3936 if (is_store && map->has_fast_elements()) {
3937 AddInstruction(new(zone()) HCheckMap(
3938 elements, isolate()->factory()->fixed_array_map()));
3939 }
3911 HInstruction* length = NULL; 3940 HInstruction* length = NULL;
3912 HInstruction* checked_key = NULL; 3941 HInstruction* checked_key = NULL;
3913 if (map->has_external_array_elements()) { 3942 if (map->has_external_array_elements()) {
3914 AddInstruction(elements);
3915 length = AddInstruction(new(zone()) HExternalArrayLength(elements)); 3943 length = AddInstruction(new(zone()) HExternalArrayLength(elements));
3916 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); 3944 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
3917 HLoadExternalArrayPointer* external_elements = 3945 HLoadExternalArrayPointer* external_elements =
3918 new(zone()) HLoadExternalArrayPointer(elements); 3946 new(zone()) HLoadExternalArrayPointer(elements);
3919 AddInstruction(external_elements); 3947 AddInstruction(external_elements);
3920 return BuildExternalArrayElementAccess(external_elements, checked_key, 3948 return BuildExternalArrayElementAccess(external_elements, checked_key,
3921 val, map->elements_kind(), is_store); 3949 val, map->elements_kind(), is_store);
3922 } 3950 }
3923 ASSERT(map->has_fast_elements()); 3951 ASSERT(map->has_fast_elements() || fast_double_elements);
3924 if (map->instance_type() == JS_ARRAY_TYPE) { 3952 if (map->instance_type() == JS_ARRAY_TYPE) {
3925 length = AddInstruction(new(zone()) HJSArrayLength(object)); 3953 length = AddInstruction(new(zone()) HJSArrayLength(object, mapcheck));
3926 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
3927 AddInstruction(elements);
3928 } else { 3954 } else {
3929 AddInstruction(elements);
3930 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); 3955 length = AddInstruction(new(zone()) HFixedArrayLength(elements));
3931 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
3932 } 3956 }
3957 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
3933 if (is_store) { 3958 if (is_store) {
3934 return new(zone()) HStoreKeyedFastElement(elements, checked_key, val); 3959 if (fast_double_elements) {
3960 return new(zone()) HStoreKeyedFastDoubleElement(elements,
3961 checked_key,
3962 val);
3963 } else {
3964 return new(zone()) HStoreKeyedFastElement(elements, checked_key, val);
3965 }
3935 } else { 3966 } else {
3936 return new(zone()) HLoadKeyedFastElement(elements, checked_key); 3967 if (fast_double_elements) {
3968 return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key);
3969 } else {
3970 return new(zone()) HLoadKeyedFastElement(elements, checked_key);
3971 }
3937 } 3972 }
3938 } 3973 }
3939 3974
3940 3975
3941 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, 3976 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
3942 HValue* key, 3977 HValue* key,
3943 HValue* val, 3978 HValue* val,
3944 Expression* prop, 3979 Expression* prop,
3945 int ast_id, 3980 int ast_id,
3946 int position, 3981 int position,
(...skipping 12 matching lines...) Expand all
3959 } 3994 }
3960 3995
3961 for (int i = 0; i < maps->length(); ++i) { 3996 for (int i = 0; i < maps->length(); ++i) {
3962 ASSERT(maps->at(i)->IsMap()); 3997 ASSERT(maps->at(i)->IsMap());
3963 type_todo[maps->at(i)->elements_kind()] = true; 3998 type_todo[maps->at(i)->elements_kind()] = true;
3964 if (maps->at(i)->elements_kind() 3999 if (maps->at(i)->elements_kind()
3965 >= JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) { 4000 >= JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) {
3966 todo_external_array = true; 4001 todo_external_array = true;
3967 } 4002 }
3968 } 4003 }
3969 // Support for FAST_DOUBLE_ELEMENTS isn't implemented yet, so we deopt.
3970 type_todo[JSObject::FAST_DOUBLE_ELEMENTS] = false;
3971 4004
3972 HBasicBlock* join = graph()->CreateBasicBlock(); 4005 HBasicBlock* join = graph()->CreateBasicBlock();
3973 4006
3974 HInstruction* elements_kind_instr = 4007 HInstruction* elements_kind_instr =
3975 AddInstruction(new(zone()) HElementsKind(object)); 4008 AddInstruction(new(zone()) HElementsKind(object));
3976 HInstruction* elements = NULL; 4009 HCompareConstantEqAndBranch* elements_kind_branch = NULL;
4010 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object));
3977 HLoadExternalArrayPointer* external_elements = NULL; 4011 HLoadExternalArrayPointer* external_elements = NULL;
3978 HInstruction* checked_key = NULL; 4012 HInstruction* checked_key = NULL;
3979 4013
3980 // FAST_ELEMENTS is assumed to be the first case. 4014 // FAST_ELEMENTS is assumed to be the first case.
3981 STATIC_ASSERT(JSObject::FAST_ELEMENTS == 0); 4015 STATIC_ASSERT(JSObject::FAST_ELEMENTS == 0);
3982 4016
3983 for (JSObject::ElementsKind elements_kind = JSObject::FAST_ELEMENTS; 4017 for (JSObject::ElementsKind elements_kind = JSObject::FAST_ELEMENTS;
3984 elements_kind <= JSObject::LAST_ELEMENTS_KIND; 4018 elements_kind <= JSObject::LAST_ELEMENTS_KIND;
3985 elements_kind = JSObject::ElementsKind(elements_kind + 1)) { 4019 elements_kind = JSObject::ElementsKind(elements_kind + 1)) {
3986 // After having handled FAST_ELEMENTS and DICTIONARY_ELEMENTS, we 4020 // After having handled FAST_ELEMENTS and DICTIONARY_ELEMENTS, we
3987 // need to add some code that's executed for all external array cases. 4021 // need to add some code that's executed for all external array cases.
3988 STATIC_ASSERT(JSObject::LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == 4022 STATIC_ASSERT(JSObject::LAST_EXTERNAL_ARRAY_ELEMENTS_KIND ==
3989 JSObject::LAST_ELEMENTS_KIND); 4023 JSObject::LAST_ELEMENTS_KIND);
3990 if (elements_kind == JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND 4024 if (elements_kind == JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND
3991 && todo_external_array) { 4025 && todo_external_array) {
3992 elements = AddInstruction(new(zone()) HLoadElements(object));
3993 // We need to forcibly prevent some ElementsKind-dependent instructions
3994 // from being hoisted out of any loops they might occur in, because
3995 // the current loop-invariant-code-motion algorithm isn't clever enough
3996 // to deal with them properly.
3997 // There's some performance to be gained by developing a smarter
3998 // solution for this.
3999 elements->ClearFlag(HValue::kUseGVN);
4000 HInstruction* length = 4026 HInstruction* length =
4001 AddInstruction(new(zone()) HExternalArrayLength(elements)); 4027 AddInstruction(new(zone()) HExternalArrayLength(elements));
4002 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); 4028 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
4003 external_elements = new(zone()) HLoadExternalArrayPointer(elements); 4029 external_elements = new(zone()) HLoadExternalArrayPointer(elements);
4004 AddInstruction(external_elements); 4030 AddInstruction(external_elements);
4005 } 4031 }
4006 if (type_todo[elements_kind]) { 4032 if (type_todo[elements_kind]) {
4007 HBasicBlock* if_true = graph()->CreateBasicBlock(); 4033 HBasicBlock* if_true = graph()->CreateBasicBlock();
4008 HBasicBlock* if_false = graph()->CreateBasicBlock(); 4034 HBasicBlock* if_false = graph()->CreateBasicBlock();
4009 HCompareConstantEqAndBranch* compare = 4035 elements_kind_branch = new(zone()) HCompareConstantEqAndBranch(
4010 new(zone()) HCompareConstantEqAndBranch(elements_kind_instr, 4036 elements_kind_instr, elements_kind, Token::EQ_STRICT);
4011 elements_kind, 4037 elements_kind_branch->SetSuccessorAt(0, if_true);
4012 Token::EQ_STRICT); 4038 elements_kind_branch->SetSuccessorAt(1, if_false);
4013 compare->SetSuccessorAt(0, if_true); 4039 current_block()->Finish(elements_kind_branch);
4014 compare->SetSuccessorAt(1, if_false);
4015 current_block()->Finish(compare);
4016 4040
4017 set_current_block(if_true); 4041 set_current_block(if_true);
4018 HInstruction* access; 4042 HInstruction* access;
4019 if (elements_kind == JSObject::FAST_ELEMENTS) { 4043 if (elements_kind == JSObject::FAST_ELEMENTS ||
4044 elements_kind == JSObject::FAST_DOUBLE_ELEMENTS) {
4045 bool fast_double_elements =
4046 elements_kind == JSObject::FAST_DOUBLE_ELEMENTS;
4047 if (is_store && elements_kind == JSObject::FAST_ELEMENTS) {
4048 AddInstruction(new(zone()) HCheckMap(
4049 elements, isolate()->factory()->fixed_array_map(),
4050 elements_kind_branch));
4051 }
4020 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); 4052 HBasicBlock* if_jsarray = graph()->CreateBasicBlock();
4021 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); 4053 HBasicBlock* if_fastobject = graph()->CreateBasicBlock();
4022 HHasInstanceTypeAndBranch* typecheck = 4054 HHasInstanceTypeAndBranch* typecheck =
4023 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); 4055 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE);
4024 typecheck->SetSuccessorAt(0, if_jsarray); 4056 typecheck->SetSuccessorAt(0, if_jsarray);
4025 typecheck->SetSuccessorAt(1, if_fastobject); 4057 typecheck->SetSuccessorAt(1, if_fastobject);
4026 current_block()->Finish(typecheck); 4058 current_block()->Finish(typecheck);
4027 4059
4028 set_current_block(if_jsarray); 4060 set_current_block(if_jsarray);
4029 HInstruction* length = new(zone()) HJSArrayLength(object); 4061 HInstruction* length = new(zone()) HJSArrayLength(object, typecheck);
4030 AddInstruction(length); 4062 AddInstruction(length);
4031 length->ClearFlag(HValue::kUseGVN);
4032 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); 4063 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
4033 elements = AddInstruction(new(zone()) HLoadElements(object));
4034 elements->ClearFlag(HValue::kUseGVN);
4035 if (is_store) { 4064 if (is_store) {
4036 access = AddInstruction( 4065 if (fast_double_elements) {
4037 new(zone()) HStoreKeyedFastElement(elements, checked_key, val)); 4066 access = AddInstruction(
4067 new(zone()) HStoreKeyedFastDoubleElement(elements,
4068 checked_key,
4069 val));
4070 } else {
4071 access = AddInstruction(
4072 new(zone()) HStoreKeyedFastElement(elements, checked_key, val));
4073 }
4038 } else { 4074 } else {
4039 access = AddInstruction( 4075 if (fast_double_elements) {
4040 new(zone()) HLoadKeyedFastElement(elements, checked_key)); 4076 access = AddInstruction(
4077 new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key));
4078 } else {
4079 access = AddInstruction(
4080 new(zone()) HLoadKeyedFastElement(elements, checked_key));
4081 }
4041 Push(access); 4082 Push(access);
4042 } 4083 }
4043 *has_side_effects |= access->HasSideEffects(); 4084 *has_side_effects |= access->HasSideEffects();
4044 if (position != -1) { 4085 if (position != -1) {
4045 access->set_position(position); 4086 access->set_position(position);
4046 } 4087 }
4047 if_jsarray->Goto(join); 4088 if_jsarray->Goto(join);
4048 4089
4049 set_current_block(if_fastobject); 4090 set_current_block(if_fastobject);
4050 elements = AddInstruction(new(zone()) HLoadElements(object));
4051 elements->ClearFlag(HValue::kUseGVN);
4052 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); 4091 length = AddInstruction(new(zone()) HFixedArrayLength(elements));
4053 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); 4092 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
4054 if (is_store) { 4093 if (is_store) {
4055 access = AddInstruction( 4094 if (fast_double_elements) {
4056 new(zone()) HStoreKeyedFastElement(elements, checked_key, val)); 4095 access = AddInstruction(
4096 new(zone()) HStoreKeyedFastDoubleElement(elements,
4097 checked_key,
4098 val));
4099 } else {
4100 access = AddInstruction(
4101 new(zone()) HStoreKeyedFastElement(elements, checked_key, val));
4102 }
4057 } else { 4103 } else {
4058 access = AddInstruction( 4104 if (fast_double_elements) {
4059 new(zone()) HLoadKeyedFastElement(elements, checked_key)); 4105 access = AddInstruction(
4106 new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key));
4107 } else {
4108 access = AddInstruction(
4109 new(zone()) HLoadKeyedFastElement(elements, checked_key));
4110 }
4060 } 4111 }
4061 } else if (elements_kind == JSObject::DICTIONARY_ELEMENTS) { 4112 } else if (elements_kind == JSObject::DICTIONARY_ELEMENTS) {
4062 if (is_store) { 4113 if (is_store) {
4063 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); 4114 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val));
4064 } else { 4115 } else {
4065 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); 4116 access = AddInstruction(BuildLoadKeyedGeneric(object, key));
4066 } 4117 }
4067 } else { // External array elements. 4118 } else { // External array elements.
4068 access = AddInstruction(BuildExternalArrayElementAccess( 4119 access = AddInstruction(BuildExternalArrayElementAccess(
4069 external_elements, checked_key, val, elements_kind, is_store)); 4120 external_elements, checked_key, val, elements_kind, is_store));
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
4174 expr->RecordTypeFeedback(oracle()); 4225 expr->RecordTypeFeedback(oracle());
4175 4226
4176 if (TryArgumentsAccess(expr)) return; 4227 if (TryArgumentsAccess(expr)) return;
4177 4228
4178 CHECK_ALIVE(VisitForValue(expr->obj())); 4229 CHECK_ALIVE(VisitForValue(expr->obj()));
4179 4230
4180 HInstruction* instr = NULL; 4231 HInstruction* instr = NULL;
4181 if (expr->IsArrayLength()) { 4232 if (expr->IsArrayLength()) {
4182 HValue* array = Pop(); 4233 HValue* array = Pop();
4183 AddInstruction(new(zone()) HCheckNonSmi(array)); 4234 AddInstruction(new(zone()) HCheckNonSmi(array));
4184 AddInstruction(HCheckInstanceType::NewIsJSArray(array)); 4235 HInstruction* mapcheck =
4185 instr = new(zone()) HJSArrayLength(array); 4236 AddInstruction(HCheckInstanceType::NewIsJSArray(array));
4237 instr = new(zone()) HJSArrayLength(array, mapcheck);
4186 4238
4187 } else if (expr->IsStringLength()) { 4239 } else if (expr->IsStringLength()) {
4188 HValue* string = Pop(); 4240 HValue* string = Pop();
4189 AddInstruction(new(zone()) HCheckNonSmi(string)); 4241 AddInstruction(new(zone()) HCheckNonSmi(string));
4190 AddInstruction(HCheckInstanceType::NewIsString(string)); 4242 AddInstruction(HCheckInstanceType::NewIsString(string));
4191 instr = new(zone()) HStringLength(string); 4243 instr = new(zone()) HStringLength(string);
4192 } else if (expr->IsStringAccess()) { 4244 } else if (expr->IsStringAccess()) {
4193 CHECK_ALIVE(VisitForValue(expr->key())); 4245 CHECK_ALIVE(VisitForValue(expr->key()));
4194 HValue* index = Pop(); 4246 HValue* index = Pop();
4195 HValue* string = Pop(); 4247 HValue* string = Pop();
(...skipping 1271 matching lines...) Expand 10 before | Expand all | Expand 10 after
5467 Visit(expr->right()); 5519 Visit(expr->right());
5468 } 5520 }
5469 5521
5470 } else if (ast_context()->IsValue()) { 5522 } else if (ast_context()->IsValue()) {
5471 CHECK_ALIVE(VisitForValue(expr->left())); 5523 CHECK_ALIVE(VisitForValue(expr->left()));
5472 ASSERT(current_block() != NULL); 5524 ASSERT(current_block() != NULL);
5473 5525
5474 // We need an extra block to maintain edge-split form. 5526 // We need an extra block to maintain edge-split form.
5475 HBasicBlock* empty_block = graph()->CreateBasicBlock(); 5527 HBasicBlock* empty_block = graph()->CreateBasicBlock();
5476 HBasicBlock* eval_right = graph()->CreateBasicBlock(); 5528 HBasicBlock* eval_right = graph()->CreateBasicBlock();
5529 unsigned test_id = expr->left()->test_id();
5530 ToBooleanStub::Types expected(oracle()->ToBooleanTypes(test_id));
5477 HBranch* test = is_logical_and 5531 HBranch* test = is_logical_and
5478 ? new(zone()) HBranch(Top(), eval_right, empty_block) 5532 ? new(zone()) HBranch(Top(), eval_right, empty_block, expected)
5479 : new(zone()) HBranch(Top(), empty_block, eval_right); 5533 : new(zone()) HBranch(Top(), empty_block, eval_right, expected);
5480 current_block()->Finish(test); 5534 current_block()->Finish(test);
5481 5535
5482 set_current_block(eval_right); 5536 set_current_block(eval_right);
5483 Drop(1); // Value of the left subexpression. 5537 Drop(1); // Value of the left subexpression.
5484 CHECK_BAILOUT(VisitForValue(expr->right())); 5538 CHECK_BAILOUT(VisitForValue(expr->right()));
5485 5539
5486 HBasicBlock* join_block = 5540 HBasicBlock* join_block =
5487 CreateJoin(empty_block, current_block(), expr->id()); 5541 CreateJoin(empty_block, current_block(), expr->id());
5488 set_current_block(join_block); 5542 set_current_block(join_block);
5489 return ast_context()->ReturnValue(Pop()); 5543 return ast_context()->ReturnValue(Pop());
(...skipping 1202 matching lines...) Expand 10 before | Expand all | Expand 10 after
6692 } 6746 }
6693 } 6747 }
6694 6748
6695 #ifdef DEBUG 6749 #ifdef DEBUG
6696 if (graph_ != NULL) graph_->Verify(); 6750 if (graph_ != NULL) graph_->Verify();
6697 if (allocator_ != NULL) allocator_->Verify(); 6751 if (allocator_ != NULL) allocator_->Verify();
6698 #endif 6752 #endif
6699 } 6753 }
6700 6754
6701 } } // namespace v8::internal 6755 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698