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

Side by Side Diff: runtime/vm/flow_graph_optimizer.cc

Issue 539153002: Port and integrate the irregexp engine from V8 (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Port remaining V8 regexp tests and fix exposed bugs. Created 6 years, 2 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
OLDNEW
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698