OLD | NEW |
---|---|
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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/regexp_assembler.h" | 5 #include "vm/regexp_assembler.h" |
6 | 6 |
7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
8 #include "vm/compiler.h" | 8 #include "vm/compiler.h" |
9 #include "vm/dart_entry.h" | 9 #include "vm/dart_entry.h" |
10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
(...skipping 16 matching lines...) Expand all Loading... | |
27 String::Handle(String::New("TAG: ")), \ | 27 String::Handle(String::New("TAG: ")), \ |
28 String::Handle(String::New(__FUNCTION__)), Heap::kOld)))))); | 28 String::Handle(String::New(__FUNCTION__)), Heap::kOld)))))); |
29 | 29 |
30 #define PRINT(arg) if (FLAG_trace_irregexp) { Print(arg); } | 30 #define PRINT(arg) if (FLAG_trace_irregexp) { Print(arg); } |
31 | 31 |
32 namespace dart { | 32 namespace dart { |
33 | 33 |
34 DEFINE_FLAG(bool, trace_irregexp, false, "Trace irregexps"); | 34 DEFINE_FLAG(bool, trace_irregexp, false, "Trace irregexps"); |
35 | 35 |
36 | 36 |
37 static const intptr_t kInvalidTryIndex = -1; | 37 static const intptr_t kInvalidTryIndex = -1; |
Florian Schneider
2014/11/12 11:38:56
static const intptr_t kInvalidTryIndex = CatchClau
zerny-google
2014/11/12 11:58:47
Done.
| |
38 static const intptr_t kNoTokenPos = -1; | 38 static const intptr_t kNoTokenPos = 0; |
Florian Schneider
2014/11/12 11:38:56
Define in terms of Scanner::kNoSourcePos which is
zerny-google
2014/11/12 11:58:47
Done.
| |
39 | 39 |
40 | 40 |
41 void PrintUtf16(uint16_t c) { | 41 void PrintUtf16(uint16_t c) { |
42 const char* format = (0x20 <= c && c <= 0x7F) ? | 42 const char* format = (0x20 <= c && c <= 0x7F) ? |
43 "%c" : (c <= 0xff) ? "\\x%02x" : "\\u%04x"; | 43 "%c" : (c <= 0xff) ? "\\x%02x" : "\\u%04x"; |
44 OS::Print(format, c); | 44 OS::Print(format, c); |
45 } | 45 } |
46 | 46 |
47 | 47 |
48 /* | 48 /* |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
116 Isolate::kNoDeoptId); | 116 Isolate::kNoDeoptId); |
117 start_block_ = | 117 start_block_ = |
118 new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex); | 118 new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex); |
119 success_block_ = | 119 success_block_ = |
120 new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex); | 120 new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex); |
121 backtrack_block_ = | 121 backtrack_block_ = |
122 new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex); | 122 new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex); |
123 exit_block_ = | 123 exit_block_ = |
124 new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex); | 124 new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex); |
125 | 125 |
126 // Allocate offsets table mapping ids of backtracking blocks to addresses. | |
127 GrowableObjectArray& offsets = GrowableObjectArray::ZoneHandle( | |
128 isolate, GrowableObjectArray::New(Heap::kOld)); | |
129 entry_block_->set_indirect_entry_offsets(&offsets); | |
130 | |
126 GenerateEntryBlock(); | 131 GenerateEntryBlock(); |
127 GenerateSuccessBlock(); | 132 GenerateSuccessBlock(); |
128 GenerateBacktrackBlock(); | 133 GenerateBacktrackBlock(); |
129 GenerateExitBlock(); | 134 GenerateExitBlock(); |
130 | 135 |
131 blocks_.Add(entry_block_); | 136 blocks_.Add(entry_block_); |
132 blocks_.Add(entry_block_->normal_entry()); | 137 blocks_.Add(entry_block_->normal_entry()); |
133 blocks_.Add(start_block_); | 138 blocks_.Add(start_block_); |
134 blocks_.Add(success_block_); | 139 blocks_.Add(success_block_); |
135 blocks_.Add(backtrack_block_); | 140 blocks_.Add(backtrack_block_); |
(...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
718 PushArgumentInstr* by_push = PushArgument(Bind(Int64Constant(by))); | 723 PushArgumentInstr* by_push = PushArgument(Bind(Int64Constant(by))); |
719 StoreLocal(position_register(reg), Bind(Add(reg_push, by_push))); | 724 StoreLocal(position_register(reg), Bind(Add(reg_push, by_push))); |
720 } | 725 } |
721 } | 726 } |
722 | 727 |
723 | 728 |
724 void IRRegExpMacroAssembler::Backtrack() { | 729 void IRRegExpMacroAssembler::Backtrack() { |
725 TAG(); | 730 TAG(); |
726 CheckPreemption(); | 731 CheckPreemption(); |
727 | 732 |
728 GrowableObjectArray& offsets = GrowableObjectArray::ZoneHandle( | 733 GrowableObjectArray& offsets = *entry_block_->indirect_entry_offsets(); |
Florian Schneider
2014/11/12 11:38:56
const GrowableObjectArray&
zerny-google
2014/11/12 11:58:47
Done.
| |
729 I, GrowableObjectArray::New(Heap::kOld)); | |
730 | 734 |
731 PushArgumentInstr* block_offsets_push = | 735 PushArgumentInstr* block_offsets_push = |
732 PushArgument(Bind(new(I) ConstantInstr(offsets))); | 736 PushArgument(Bind(new(I) ConstantInstr(offsets))); |
733 PushArgumentInstr* block_id_push = PushArgument(PopStack()); | 737 PushArgumentInstr* block_id_push = PushArgument(PopStack()); |
734 | 738 |
735 Value* offset_value = | 739 Value* offset_value = |
736 Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX), | 740 Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX), |
737 block_offsets_push, | 741 block_offsets_push, |
738 block_id_push)); | 742 block_id_push)); |
739 | 743 |
740 IndirectGotoInstr* igoto = new(I) IndirectGotoInstr(&offsets, offset_value); | 744 IndirectGotoInstr* igoto = new(I) IndirectGotoInstr(offset_value); |
741 CloseBlockWith(igoto); | 745 CloseBlockWith(igoto); |
742 igotos_.Add(igoto); | 746 igotos_.Add(igoto); |
743 } | 747 } |
744 | 748 |
745 | 749 |
746 // A BindBlock is analogous to assigning a label to a basic block. | 750 // A BindBlock is analogous to assigning a label to a basic block. |
747 // If the BlockLabel does not yet contain a block, it is created. | 751 // If the BlockLabel does not yet contain a block, it is created. |
748 // If there is a current instruction, append a goto to the bound block. | 752 // If there is a current instruction, append a goto to the bound block. |
749 void IRRegExpMacroAssembler::BindBlock(BlockLabel* label) { | 753 void IRRegExpMacroAssembler::BindBlock(BlockLabel* label) { |
750 ASSERT(!label->IsBound()); | 754 ASSERT(!label->IsBound()); |
(...skipping 21 matching lines...) Expand all Loading... | |
772 LocalVariable* IRRegExpMacroAssembler::position_register(intptr_t index) { | 776 LocalVariable* IRRegExpMacroAssembler::position_register(intptr_t index) { |
773 // Create position registers as needed. | 777 // Create position registers as needed. |
774 for (intptr_t i = position_registers_.length(); i < index + 1; i++) { | 778 for (intptr_t i = position_registers_.length(); i < index + 1; i++) { |
775 position_registers_.Add(Local(Symbols::position_registers_())); | 779 position_registers_.Add(Local(Symbols::position_registers_())); |
776 } | 780 } |
777 | 781 |
778 return position_registers_[index]; | 782 return position_registers_[index]; |
779 } | 783 } |
780 | 784 |
781 | 785 |
782 // TODO(zerny): Move the offset table outside to avoid having to keep | 786 void IRRegExpMacroAssembler::FinalizeBlockOffsetTable(Isolate* isolate, |
783 // the assembler around until after code generation; both function or regexp | 787 GraphEntryInstr* graph) { |
784 // would work. | 788 const GrowableArray<IndirectEntryInstr*>& entries = graph->indirect_entries(); |
785 void IRRegExpMacroAssembler::FinalizeBlockOffsetTable() { | 789 const intptr_t count = entries.length(); |
786 for (intptr_t i = 0; i < igotos_.length(); i++) { | 790 if (!count) return; |
Florian Schneider
2014/11/12 11:38:56
Use count == 0 instead here.
zerny-google
2014/11/12 11:58:47
Ok. But I rather removed the early return here.
| |
787 IndirectGotoInstr* igoto = igotos_[i]; | 791 GrowableObjectArray* offsets = graph->indirect_entry_offsets(); |
788 igoto->SetOffsetCount(I, indirect_id_.Count()); | 792 if (offsets->Capacity() < count) { |
789 | 793 offsets->Grow(count, Heap::kOld); |
790 for (intptr_t j = 0; j < igoto->SuccessorCount(); j++) { | 794 } |
791 TargetEntryInstr* target = igoto->SuccessorAt(j); | 795 if (offsets->Length() < count) { |
792 | 796 offsets->SetLength(count); |
793 // Optimizations might have modified the immediate target block, but | 797 } |
794 // it must end with a goto to the indirect entry. | 798 for (intptr_t i = 0; i < count; ++i) { |
795 Instruction* instr = target; | 799 IndirectEntryInstr* entry = entries[i]; |
796 while (instr != NULL && !instr->IsGoto()) { | 800 if (entry->offset() <= 0) { |
797 instr = instr->next(); | 801 // An invalid offset signifies an unreachable block. |
798 } | 802 // TODO(zerny): We should guard against usage of an invalid index. |
799 ASSERT(instr->IsGoto()); | 803 continue; |
800 | |
801 IndirectEntryInstr* ientry = | |
802 instr->AsGoto()->successor()->AsIndirectEntry(); | |
803 ASSERT(ientry != NULL); | |
804 | |
805 // The intermediate block was possibly compacted, check both it and the | |
806 // final indirect entry for a valid offset. If neither are valid, then | |
807 // the indirect entry is unreachable. | |
808 intptr_t offset = | |
809 (target->offset() > 0) ? target->offset() : ientry->offset(); | |
810 if (offset > 0) { | |
811 intptr_t adjusted_offset = | |
812 offset - Assembler::EntryPointToPcMarkerOffset(); | |
813 igoto->SetOffsetAt(I, ientry->indirect_id(), adjusted_offset); | |
814 } | |
815 } | 804 } |
805 intptr_t offset = entry->offset() - Assembler::EntryPointToPcMarkerOffset(); | |
806 offsets->SetAt(i, Smi::ZoneHandle(isolate, Smi::New(offset))); | |
816 } | 807 } |
817 } | 808 } |
818 | 809 |
810 | |
819 void IRRegExpMacroAssembler::FinalizeIndirectGotos() { | 811 void IRRegExpMacroAssembler::FinalizeIndirectGotos() { |
820 for (intptr_t i = 0; i < igotos_.length(); i++) { | 812 for (intptr_t i = 0; i < igotos_.length(); i++) { |
821 for (intptr_t j = 0; j < entry_block_->indirect_entries().length(); j++) { | 813 for (intptr_t j = 0; j < entry_block_->indirect_entries().length(); j++) { |
822 igotos_.At(i)->AddSuccessor( | 814 igotos_.At(i)->AddSuccessor( |
823 TargetWithJoinGoto(entry_block_->indirect_entries().At(j))); | 815 TargetWithJoinGoto(entry_block_->indirect_entries().At(j))); |
824 } | 816 } |
825 } | 817 } |
826 } | 818 } |
827 | 819 |
828 | 820 |
(...skipping 1015 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1844 index, | 1836 index, |
1845 characters, | 1837 characters, |
1846 specialization_cid_, | 1838 specialization_cid_, |
1847 Scanner::kNoSourcePos)); | 1839 Scanner::kNoSourcePos)); |
1848 } | 1840 } |
1849 | 1841 |
1850 | 1842 |
1851 #undef __ | 1843 #undef __ |
1852 | 1844 |
1853 } // namespace dart | 1845 } // namespace dart |
OLD | NEW |