Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/flow_graph_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
| 9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| 11 #include "vm/exceptions.h" | 11 #include "vm/exceptions.h" |
| 12 #include "vm/flow_graph_builder.h" | 12 #include "vm/flow_graph_builder.h" |
| 13 #include "vm/flow_graph_compiler.h" | 13 #include "vm/flow_graph_compiler.h" |
| 14 #include "vm/flow_graph_range_analysis.h" | 14 #include "vm/flow_graph_range_analysis.h" |
| 15 #include "vm/hash_map.h" | 15 #include "vm/hash_map.h" |
| 16 #include "vm/il_printer.h" | 16 #include "vm/il_printer.h" |
| 17 #include "vm/intermediate_language.h" | 17 #include "vm/intermediate_language.h" |
| 18 #include "vm/object_store.h" | 18 #include "vm/object_store.h" |
| 19 #include "vm/parser.h" | 19 #include "vm/parser.h" |
| 20 #include "vm/regexp_assembler.h" | |
| 20 #include "vm/resolver.h" | 21 #include "vm/resolver.h" |
| 21 #include "vm/scopes.h" | 22 #include "vm/scopes.h" |
| 22 #include "vm/stack_frame.h" | 23 #include "vm/stack_frame.h" |
| 23 #include "vm/symbols.h" | 24 #include "vm/symbols.h" |
| 24 | 25 |
| 25 namespace dart { | 26 namespace dart { |
| 26 | 27 |
| 27 DEFINE_FLAG(int, getter_setter_ratio, 13, | 28 DEFINE_FLAG(int, getter_setter_ratio, 13, |
| 28 "Ratio of getter/setter usage used for double field unboxing heuristics"); | 29 "Ratio of getter/setter usage used for double field unboxing heuristics"); |
| 29 DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination."); | 30 DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination."); |
| (...skipping 1594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1624 if (!ShouldInlineSimd()) { | 1625 if (!ShouldInlineSimd()) { |
| 1625 return false; | 1626 return false; |
| 1626 } | 1627 } |
| 1627 return InlineByteArrayViewStore(target, call, receiver, receiver_cid, | 1628 return InlineByteArrayViewStore(target, call, receiver, receiver_cid, |
| 1628 kTypedDataInt32x4ArrayCid, | 1629 kTypedDataInt32x4ArrayCid, |
| 1629 ic_data, entry, last); | 1630 ic_data, entry, last); |
| 1630 case MethodRecognizer::kStringBaseCodeUnitAt: | 1631 case MethodRecognizer::kStringBaseCodeUnitAt: |
| 1631 return InlineStringCodeUnitAt(call, receiver_cid, entry, last); | 1632 return InlineStringCodeUnitAt(call, receiver_cid, entry, last); |
| 1632 case MethodRecognizer::kStringBaseCharAt: | 1633 case MethodRecognizer::kStringBaseCharAt: |
| 1633 return InlineStringBaseCharAt(call, receiver_cid, entry, last); | 1634 return InlineStringBaseCharAt(call, receiver_cid, entry, last); |
| 1635 case MethodRecognizer::kOneByteString_oneCodeUnitAt: | |
| 1636 case MethodRecognizer::kTwoByteString_oneCodeUnitAt: | |
| 1637 return InlineStringCodeUnitsAt(call, receiver_cid, 1, entry, last); | |
| 1638 case MethodRecognizer::kOneByteString_twoCodeUnitsAt: | |
| 1639 case MethodRecognizer::kTwoByteString_twoCodeUnitsAt: | |
| 1640 return InlineStringCodeUnitsAt(call, receiver_cid, 2, entry, last); | |
| 1641 case MethodRecognizer::kOneByteString_fourCodeUnitsAt: | |
| 1642 return InlineStringCodeUnitsAt(call, receiver_cid, 4, entry, last); | |
| 1634 case MethodRecognizer::kDoubleAdd: | 1643 case MethodRecognizer::kDoubleAdd: |
| 1635 return InlineDoubleOp(Token::kADD, call, entry, last); | 1644 return InlineDoubleOp(Token::kADD, call, entry, last); |
| 1636 case MethodRecognizer::kDoubleSub: | 1645 case MethodRecognizer::kDoubleSub: |
| 1637 return InlineDoubleOp(Token::kSUB, call, entry, last); | 1646 return InlineDoubleOp(Token::kSUB, call, entry, last); |
| 1638 case MethodRecognizer::kDoubleMul: | 1647 case MethodRecognizer::kDoubleMul: |
| 1639 return InlineDoubleOp(Token::kMUL, call, entry, last); | 1648 return InlineDoubleOp(Token::kMUL, call, entry, last); |
| 1640 case MethodRecognizer::kDoubleDiv: | 1649 case MethodRecognizer::kDoubleDiv: |
| 1641 return InlineDoubleOp(Token::kDIV, call, entry, last); | 1650 return InlineDoubleOp(Token::kDIV, call, entry, last); |
| 1642 default: | 1651 default: |
| 1643 return false; | 1652 return false; |
| (...skipping 1189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2833 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), | 2842 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), |
| 2834 call->GetBlock()->try_index()); | 2843 call->GetBlock()->try_index()); |
| 2835 (*entry)->InheritDeoptTarget(I, call); | 2844 (*entry)->InheritDeoptTarget(I, call); |
| 2836 | 2845 |
| 2837 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); | 2846 *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); |
| 2838 | 2847 |
| 2839 return true; | 2848 return true; |
| 2840 } | 2849 } |
| 2841 | 2850 |
| 2842 | 2851 |
| 2852 Definition* FlowGraphOptimizer::PrepareInlineStringIndexOpUnchecked( | |
| 2853 Instruction* call, | |
| 2854 intptr_t cid, | |
| 2855 intptr_t count, | |
| 2856 Definition* str, | |
| 2857 Definition* index, | |
| 2858 Instruction* cursor) { | |
| 2859 LoadCodeUnitsInstr* load = new(I) LoadCodeUnitsInstr( | |
|
Vyacheslav Egorov (Google)
2014/10/01 20:13:21
[ignore this comment]
This is *a*whole*lot* of co
jgruber1
2014/10/03 18:59:51
I agree, the reason behind this was that LoadIndex
| |
| 2860 new(I) Value(str), | |
| 2861 new(I) Value(index), | |
| 2862 Instance::ElementSizeFor(cid), | |
| 2863 count, | |
| 2864 cid, | |
| 2865 Isolate::kNoDeoptId, | |
| 2866 call->token_pos()); | |
| 2867 | |
| 2868 cursor = flow_graph()->AppendTo(cursor, | |
| 2869 load, | |
| 2870 NULL, | |
| 2871 FlowGraph::kValue); | |
| 2872 ASSERT(cursor == load); | |
| 2873 return load; | |
| 2874 } | |
| 2875 | |
| 2876 | |
| 2877 bool FlowGraphOptimizer::InlineStringCodeUnitsAt( | |
| 2878 Instruction* call, | |
| 2879 intptr_t cid, | |
| 2880 intptr_t count, | |
| 2881 TargetEntryInstr** entry, | |
| 2882 Definition** last) { | |
| 2883 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. | |
| 2884 if (RawObject::IsExternalStringClassId(cid)) { | |
| 2885 return false; | |
| 2886 } | |
| 2887 | |
| 2888 Definition* str = call->ArgumentAt(0); | |
| 2889 Definition* index = call->ArgumentAt(1); | |
| 2890 | |
| 2891 *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(), | |
| 2892 call->GetBlock()->try_index()); | |
| 2893 (*entry)->InheritDeoptTarget(I, call); | |
| 2894 | |
| 2895 *last = PrepareInlineStringIndexOpUnchecked( | |
| 2896 call, cid, count, str, index, *entry); | |
| 2897 | |
| 2898 return true; | |
| 2899 } | |
| 2900 | |
| 2901 | |
| 2843 bool FlowGraphOptimizer::InlineStringBaseCharAt( | 2902 bool FlowGraphOptimizer::InlineStringBaseCharAt( |
| 2844 Instruction* call, | 2903 Instruction* call, |
| 2845 intptr_t cid, | 2904 intptr_t cid, |
| 2846 TargetEntryInstr** entry, | 2905 TargetEntryInstr** entry, |
| 2847 Definition** last) { | 2906 Definition** last) { |
| 2848 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. | 2907 // TODO(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. |
| 2849 if (RawObject::IsExternalStringClassId(cid) || cid != kOneByteStringCid) { | 2908 if (RawObject::IsExternalStringClassId(cid) || cid != kOneByteStringCid) { |
| 2850 return false; | 2909 return false; |
| 2851 } | 2910 } |
| 2852 Definition* str = call->ArgumentAt(0); | 2911 Definition* str = call->ArgumentAt(0); |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3025 Bigint::neg_offset(), | 3084 Bigint::neg_offset(), |
| 3026 new(I) Value(bigint), | 3085 new(I) Value(bigint), |
| 3027 new(I) Value(value), | 3086 new(I) Value(value), |
| 3028 kEmitStoreBarrier, | 3087 kEmitStoreBarrier, |
| 3029 call->token_pos()); | 3088 call->token_pos()); |
| 3030 ReplaceCall(call, store); | 3089 ReplaceCall(call, store); |
| 3031 return true; | 3090 return true; |
| 3032 } | 3091 } |
| 3033 | 3092 |
| 3034 if (((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) || | 3093 if (((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) || |
| 3035 (recognized_kind == MethodRecognizer::kStringBaseCharAt)) && | 3094 (recognized_kind == MethodRecognizer::kStringBaseCharAt) || |
| 3095 (recognized_kind == MethodRecognizer::kOneByteString_oneCodeUnitAt) || | |
| 3096 (recognized_kind == MethodRecognizer::kOneByteString_twoCodeUnitsAt) || | |
| 3097 (recognized_kind == MethodRecognizer::kOneByteString_fourCodeUnitsAt) || | |
| 3098 (recognized_kind == MethodRecognizer::kTwoByteString_oneCodeUnitAt) || | |
| 3099 (recognized_kind == MethodRecognizer::kTwoByteString_twoCodeUnitsAt)) && | |
| 3036 (ic_data.NumberOfChecks() == 1) && | 3100 (ic_data.NumberOfChecks() == 1) && |
| 3037 ((class_ids[0] == kOneByteStringCid) || | 3101 ((class_ids[0] == kOneByteStringCid) || |
| 3038 (class_ids[0] == kTwoByteStringCid))) { | 3102 (class_ids[0] == kTwoByteStringCid))) { |
| 3039 return TryReplaceInstanceCallWithInline(call); | 3103 return TryReplaceInstanceCallWithInline(call); |
| 3040 } | 3104 } |
| 3041 | 3105 |
| 3042 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) { | 3106 if ((class_ids[0] == kOneByteStringCid) && (ic_data.NumberOfChecks() == 1)) { |
| 3043 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { | 3107 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) { |
| 3044 // This is an internal method, no need to check argument types nor | 3108 // This is an internal method, no need to check argument types nor |
| 3045 // range. | 3109 // range. |
| (...skipping 4634 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7680 } | 7744 } |
| 7681 | 7745 |
| 7682 | 7746 |
| 7683 void ConstantPropagator::VisitTargetEntry(TargetEntryInstr* block) { | 7747 void ConstantPropagator::VisitTargetEntry(TargetEntryInstr* block) { |
| 7684 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 7748 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 7685 it.Current()->Accept(this); | 7749 it.Current()->Accept(this); |
| 7686 } | 7750 } |
| 7687 } | 7751 } |
| 7688 | 7752 |
| 7689 | 7753 |
| 7754 void ConstantPropagator::VisitIndirectEntry(IndirectEntryInstr* block) { | |
| 7755 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | |
| 7756 it.Current()->Accept(this); | |
| 7757 } | |
| 7758 } | |
| 7759 | |
| 7760 | |
| 7690 void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) { | 7761 void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) { |
| 7691 const GrowableArray<Definition*>& defs = *block->initial_definitions(); | 7762 const GrowableArray<Definition*>& defs = *block->initial_definitions(); |
| 7692 for (intptr_t i = 0; i < defs.length(); ++i) { | 7763 for (intptr_t i = 0; i < defs.length(); ++i) { |
| 7693 defs[i]->Accept(this); | 7764 defs[i]->Accept(this); |
| 7694 } | 7765 } |
| 7695 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 7766 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 7696 it.Current()->Accept(this); | 7767 it.Current()->Accept(this); |
| 7697 } | 7768 } |
| 7698 } | 7769 } |
| 7699 | 7770 |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 7727 SetReachable(instr->successor()); | 7798 SetReachable(instr->successor()); |
| 7728 | 7799 |
| 7729 // Phi value depends on the reachability of a predecessor. We have | 7800 // Phi value depends on the reachability of a predecessor. We have |
| 7730 // to revisit phis every time a predecessor becomes reachable. | 7801 // to revisit phis every time a predecessor becomes reachable. |
| 7731 for (PhiIterator it(instr->successor()); !it.Done(); it.Advance()) { | 7802 for (PhiIterator it(instr->successor()); !it.Done(); it.Advance()) { |
| 7732 it.Current()->Accept(this); | 7803 it.Current()->Accept(this); |
| 7733 } | 7804 } |
| 7734 } | 7805 } |
| 7735 | 7806 |
| 7736 | 7807 |
| 7808 void ConstantPropagator::VisitIndirectGoto(IndirectGotoInstr* instr) { | |
| 7809 for (intptr_t i = 0; i < instr->SuccessorCount(); i++) { | |
| 7810 SetReachable(instr->SuccessorAt(i)); | |
| 7811 } | |
| 7812 } | |
| 7813 | |
| 7814 | |
| 7737 void ConstantPropagator::VisitBranch(BranchInstr* instr) { | 7815 void ConstantPropagator::VisitBranch(BranchInstr* instr) { |
| 7738 instr->comparison()->Accept(this); | 7816 instr->comparison()->Accept(this); |
| 7739 | 7817 |
| 7740 // The successors may be reachable, but only if this instruction is. (We | 7818 // The successors may be reachable, but only if this instruction is. (We |
| 7741 // might be analyzing it because the constant value of one of its inputs | 7819 // might be analyzing it because the constant value of one of its inputs |
| 7742 // has changed.) | 7820 // has changed.) |
| 7743 if (reachable_->Contains(instr->GetBlock()->preorder_number())) { | 7821 if (reachable_->Contains(instr->GetBlock()->preorder_number())) { |
| 7744 if (instr->constant_target() != NULL) { | 7822 if (instr->constant_target() != NULL) { |
| 7745 ASSERT((instr->constant_target() == instr->true_successor()) || | 7823 ASSERT((instr->constant_target() == instr->true_successor()) || |
| 7746 (instr->constant_target() == instr->false_successor())); | 7824 (instr->constant_target() == instr->false_successor())); |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8138 SetValue(instr, result); | 8216 SetValue(instr, result); |
| 8139 return; | 8217 return; |
| 8140 } | 8218 } |
| 8141 } | 8219 } |
| 8142 } | 8220 } |
| 8143 SetValue(instr, non_constant_); | 8221 SetValue(instr, non_constant_); |
| 8144 } | 8222 } |
| 8145 } | 8223 } |
| 8146 | 8224 |
| 8147 | 8225 |
| 8226 void ConstantPropagator::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) { | |
| 8227 // TODO(jgruber): Implement constant propagation. | |
| 8228 SetValue(instr, non_constant_); | |
| 8229 } | |
| 8230 | |
| 8231 | |
| 8148 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) { | 8232 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) { |
| 8149 SetValue(instr, instr->value()->definition()->constant_value()); | 8233 SetValue(instr, instr->value()->definition()->constant_value()); |
| 8150 } | 8234 } |
| 8151 | 8235 |
| 8152 | 8236 |
| 8153 void ConstantPropagator::VisitStoreInstanceField( | 8237 void ConstantPropagator::VisitStoreInstanceField( |
| 8154 StoreInstanceFieldInstr* instr) { | 8238 StoreInstanceFieldInstr* instr) { |
| 8155 SetValue(instr, instr->value()->definition()->constant_value()); | 8239 SetValue(instr, instr->value()->definition()->constant_value()); |
| 8156 } | 8240 } |
| 8157 | 8241 |
| (...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8780 const Object& right = instr->right()->definition()->constant_value(); | 8864 const Object& right = instr->right()->definition()->constant_value(); |
| 8781 if (IsNonConstant(left) || IsNonConstant(right)) { | 8865 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 8782 SetValue(instr, non_constant_); | 8866 SetValue(instr, non_constant_); |
| 8783 } else if (IsConstant(left) && IsConstant(right)) { | 8867 } else if (IsConstant(left) && IsConstant(right)) { |
| 8784 // TODO(srdjan): Handle min and max. | 8868 // TODO(srdjan): Handle min and max. |
| 8785 SetValue(instr, non_constant_); | 8869 SetValue(instr, non_constant_); |
| 8786 } | 8870 } |
| 8787 } | 8871 } |
| 8788 | 8872 |
| 8789 | 8873 |
| 8874 void ConstantPropagator::VisitCaseInsensitiveCompareUC16( | |
| 8875 CaseInsensitiveCompareUC16Instr *instr) { | |
|
Florian Schneider
2014/10/01 17:04:13
Not sure if it's actually worth supporting: do you
jgruber1
2014/10/03 18:59:51
Done.
| |
| 8876 const Object& str = instr->str()->definition()->constant_value(); | |
| 8877 const Object& lhs_index = instr->lhs_index()->definition()->constant_value(); | |
| 8878 const Object& rhs_index = instr->rhs_index()->definition()->constant_value(); | |
| 8879 const Object& length = instr->length()->definition()->constant_value(); | |
| 8880 | |
| 8881 if (IsConstant(str) && str.IsString() && | |
| 8882 IsConstant(lhs_index) && lhs_index.IsSmi() && | |
| 8883 IsConstant(rhs_index) && rhs_index.IsSmi() && | |
| 8884 IsConstant(length) && length.IsSmi()) { | |
| 8885 const Bool& result = | |
| 8886 Bool::Handle(isolate(), | |
| 8887 IRRegExpMacroAssembler::CaseInsensitiveCompareUC16( | |
| 8888 String::Cast(str).raw(), | |
| 8889 Smi::Cast(lhs_index).raw(), | |
| 8890 Smi::Cast(rhs_index).raw(), | |
| 8891 Smi::Cast(length).raw())); | |
| 8892 SetValue(instr, result); | |
| 8893 } else { | |
| 8894 SetValue(instr, non_constant_); | |
| 8895 } | |
| 8896 } | |
| 8897 | |
| 8898 | |
| 8790 void ConstantPropagator::VisitUnboxDouble(UnboxDoubleInstr* instr) { | 8899 void ConstantPropagator::VisitUnboxDouble(UnboxDoubleInstr* instr) { |
| 8791 const Object& value = instr->value()->definition()->constant_value(); | 8900 const Object& value = instr->value()->definition()->constant_value(); |
| 8792 if (IsNonConstant(value)) { | 8901 if (IsNonConstant(value)) { |
| 8793 SetValue(instr, non_constant_); | 8902 SetValue(instr, non_constant_); |
| 8794 } else if (IsConstant(value)) { | 8903 } else if (IsConstant(value)) { |
| 8795 // TODO(kmillikin): Handle conversion. | 8904 // TODO(kmillikin): Handle conversion. |
| 8796 SetValue(instr, non_constant_); | 8905 SetValue(instr, non_constant_); |
| 8797 } | 8906 } |
| 8798 } | 8907 } |
| 8799 | 8908 |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8929 } else { | 9038 } else { |
| 8930 BlockEntryInstr* block = block_worklist_.RemoveLast(); | 9039 BlockEntryInstr* block = block_worklist_.RemoveLast(); |
| 8931 block->Accept(this); | 9040 block->Accept(this); |
| 8932 } | 9041 } |
| 8933 } | 9042 } |
| 8934 } | 9043 } |
| 8935 | 9044 |
| 8936 | 9045 |
| 8937 static bool IsEmptyBlock(BlockEntryInstr* block) { | 9046 static bool IsEmptyBlock(BlockEntryInstr* block) { |
| 8938 return block->next()->IsGoto() && | 9047 return block->next()->IsGoto() && |
| 8939 (!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)); | 9048 (!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)) && |
| 9049 !block->IsIndirectEntry(); | |
| 8940 } | 9050 } |
| 8941 | 9051 |
| 8942 | 9052 |
| 8943 // Traverses a chain of empty blocks and returns the first reachable non-empty | 9053 // Traverses a chain of empty blocks and returns the first reachable non-empty |
| 8944 // block that is not dominated by the start block. The empty blocks are added | 9054 // block that is not dominated by the start block. The empty blocks are added |
| 8945 // to the supplied bit vector. | 9055 // to the supplied bit vector. |
| 8946 static BlockEntryInstr* FindFirstNonEmptySuccessor( | 9056 static BlockEntryInstr* FindFirstNonEmptySuccessor( |
| 8947 TargetEntryInstr* block, | 9057 TargetEntryInstr* block, |
| 8948 BitVector* empty_blocks) { | 9058 BitVector* empty_blocks) { |
| 8949 BlockEntryInstr* current = block; | 9059 BlockEntryInstr* current = block; |
| (...skipping 1170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10120 | 10230 |
| 10121 // Insert materializations at environment uses. | 10231 // Insert materializations at environment uses. |
| 10122 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 10232 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
| 10123 CreateMaterializationAt( | 10233 CreateMaterializationAt( |
| 10124 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); | 10234 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); |
| 10125 } | 10235 } |
| 10126 } | 10236 } |
| 10127 | 10237 |
| 10128 | 10238 |
| 10129 } // namespace dart | 10239 } // namespace dart |
| OLD | NEW |