| 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 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 GenerateEntryBlock(); | 126 GenerateEntryBlock(); |
| 127 GenerateSuccessBlock(); | 127 GenerateSuccessBlock(); |
| 128 GenerateBacktrackBlock(); | |
| 129 GenerateExitBlock(); | 128 GenerateExitBlock(); |
| 130 | 129 |
| 131 blocks_.Add(entry_block_); | 130 blocks_.Add(entry_block_); |
| 132 blocks_.Add(entry_block_->normal_entry()); | 131 blocks_.Add(entry_block_->normal_entry()); |
| 133 blocks_.Add(start_block_); | 132 blocks_.Add(start_block_); |
| 134 blocks_.Add(success_block_); | 133 blocks_.Add(success_block_); |
| 135 blocks_.Add(backtrack_block_); | 134 blocks_.Add(backtrack_block_); |
| 136 blocks_.Add(exit_block_); | 135 blocks_.Add(exit_block_); |
| 137 | 136 |
| 138 // Begin emission at the start_block_. | 137 // Begin emission at the start_block_. |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 StoreLocal(current_position_, Bind(Sub(start_index_push, length_push))); | 200 StoreLocal(current_position_, Bind(Sub(start_index_push, length_push))); |
| 202 | 201 |
| 203 // Jump to the start block. | 202 // Jump to the start block. |
| 204 current_instruction_->Goto(start_block_); | 203 current_instruction_->Goto(start_block_); |
| 205 } | 204 } |
| 206 | 205 |
| 207 | 206 |
| 208 void IRRegExpMacroAssembler::GenerateBacktrackBlock() { | 207 void IRRegExpMacroAssembler::GenerateBacktrackBlock() { |
| 209 set_current_instruction(backtrack_block_); | 208 set_current_instruction(backtrack_block_); |
| 210 TAG(); | 209 TAG(); |
| 211 Backtrack(); | 210 CheckPreemption(); |
| 211 |
| 212 const intptr_t entries_count = entry_block_->indirect_entries().length(); |
| 213 |
| 214 GrowableObjectArray& offsets = GrowableObjectArray::ZoneHandle( |
| 215 I, GrowableObjectArray::New(entries_count, Heap::kOld)); |
| 216 |
| 217 PushArgumentInstr* block_offsets_push = |
| 218 PushArgument(Bind(new(I) ConstantInstr(offsets))); |
| 219 PushArgumentInstr* block_id_push = PushArgument(PopStack()); |
| 220 |
| 221 Value* offset_value = |
| 222 Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX), |
| 223 block_offsets_push, |
| 224 block_id_push)); |
| 225 |
| 226 backtrack_goto_ = new(I) IndirectGotoInstr(&offsets, offset_value); |
| 227 CloseBlockWith(backtrack_goto_); |
| 228 |
| 229 // Add an edge from the "indirect" goto to each of the targets. |
| 230 for (intptr_t j = 0; j < entries_count; j++) { |
| 231 backtrack_goto_->AddSuccessor( |
| 232 TargetWithJoinGoto(entry_block_->indirect_entries().At(j))); |
| 233 } |
| 212 } | 234 } |
| 213 | 235 |
| 214 | 236 |
| 215 void IRRegExpMacroAssembler::GenerateSuccessBlock() { | 237 void IRRegExpMacroAssembler::GenerateSuccessBlock() { |
| 216 set_current_instruction(success_block_); | 238 set_current_instruction(success_block_); |
| 217 TAG(); | 239 TAG(); |
| 218 | 240 |
| 219 Definition* type_args_null_def = new(I) ConstantInstr( | 241 Definition* type_args_null_def = new(I) ConstantInstr( |
| 220 TypeArguments::ZoneHandle(I, TypeArguments::null())); | 242 TypeArguments::ZoneHandle(I, TypeArguments::null())); |
| 221 PushArgumentInstr* type_arg_push = PushArgument(Bind(type_args_null_def)); | 243 PushArgumentInstr* type_arg_push = PushArgument(Bind(type_args_null_def)); |
| (...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 716 if (by != 0) { | 738 if (by != 0) { |
| 717 PushArgumentInstr* reg_push = PushLocal(position_register(reg)); | 739 PushArgumentInstr* reg_push = PushLocal(position_register(reg)); |
| 718 PushArgumentInstr* by_push = PushArgument(Bind(Int64Constant(by))); | 740 PushArgumentInstr* by_push = PushArgument(Bind(Int64Constant(by))); |
| 719 StoreLocal(position_register(reg), Bind(Add(reg_push, by_push))); | 741 StoreLocal(position_register(reg), Bind(Add(reg_push, by_push))); |
| 720 } | 742 } |
| 721 } | 743 } |
| 722 | 744 |
| 723 | 745 |
| 724 void IRRegExpMacroAssembler::Backtrack() { | 746 void IRRegExpMacroAssembler::Backtrack() { |
| 725 TAG(); | 747 TAG(); |
| 726 CheckPreemption(); | 748 GoTo(backtrack_block_); |
| 727 | |
| 728 GrowableObjectArray& offsets = GrowableObjectArray::ZoneHandle( | |
| 729 I, GrowableObjectArray::New(Heap::kOld)); | |
| 730 | |
| 731 PushArgumentInstr* block_offsets_push = | |
| 732 PushArgument(Bind(new(I) ConstantInstr(offsets))); | |
| 733 PushArgumentInstr* block_id_push = PushArgument(PopStack()); | |
| 734 | |
| 735 Value* offset_value = | |
| 736 Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX), | |
| 737 block_offsets_push, | |
| 738 block_id_push)); | |
| 739 | |
| 740 IndirectGotoInstr* igoto = new(I) IndirectGotoInstr(&offsets, offset_value); | |
| 741 CloseBlockWith(igoto); | |
| 742 igotos_.Add(igoto); | |
| 743 } | 749 } |
| 744 | 750 |
| 745 | 751 |
| 746 // A BindBlock is analogous to assigning a label to a basic block. | 752 // 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. | 753 // 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. | 754 // If there is a current instruction, append a goto to the bound block. |
| 749 void IRRegExpMacroAssembler::BindBlock(BlockLabel* label) { | 755 void IRRegExpMacroAssembler::BindBlock(BlockLabel* label) { |
| 750 ASSERT(!label->IsBound()); | 756 ASSERT(!label->IsBound()); |
| 751 ASSERT(label->block()->next() == NULL); | 757 ASSERT(label->block()->next() == NULL); |
| 752 | 758 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 772 LocalVariable* IRRegExpMacroAssembler::position_register(intptr_t index) { | 778 LocalVariable* IRRegExpMacroAssembler::position_register(intptr_t index) { |
| 773 // Create position registers as needed. | 779 // Create position registers as needed. |
| 774 for (intptr_t i = position_registers_.length(); i < index + 1; i++) { | 780 for (intptr_t i = position_registers_.length(); i < index + 1; i++) { |
| 775 position_registers_.Add(Local(Symbols::position_registers_())); | 781 position_registers_.Add(Local(Symbols::position_registers_())); |
| 776 } | 782 } |
| 777 | 783 |
| 778 return position_registers_[index]; | 784 return position_registers_[index]; |
| 779 } | 785 } |
| 780 | 786 |
| 781 | 787 |
| 782 // TODO(zerny): Move the offset table outside to avoid having to keep | |
| 783 // the assembler around until after code generation; both function or regexp | |
| 784 // would work. | |
| 785 void IRRegExpMacroAssembler::FinalizeBlockOffsetTable() { | |
| 786 for (intptr_t i = 0; i < igotos_.length(); i++) { | |
| 787 IndirectGotoInstr* igoto = igotos_[i]; | |
| 788 igoto->SetOffsetCount(I, indirect_id_.Count()); | |
| 789 | |
| 790 for (intptr_t j = 0; j < igoto->SuccessorCount(); j++) { | |
| 791 TargetEntryInstr* target = igoto->SuccessorAt(j); | |
| 792 | |
| 793 // Optimizations might have modified the immediate target block, but | |
| 794 // it must end with a goto to the indirect entry. | |
| 795 Instruction* instr = target; | |
| 796 while (instr != NULL && !instr->IsGoto()) { | |
| 797 instr = instr->next(); | |
| 798 } | |
| 799 ASSERT(instr->IsGoto()); | |
| 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 } | |
| 816 } | |
| 817 } | |
| 818 | |
| 819 void IRRegExpMacroAssembler::FinalizeIndirectGotos() { | |
| 820 for (intptr_t i = 0; i < igotos_.length(); i++) { | |
| 821 for (intptr_t j = 0; j < entry_block_->indirect_entries().length(); j++) { | |
| 822 igotos_.At(i)->AddSuccessor( | |
| 823 TargetWithJoinGoto(entry_block_->indirect_entries().At(j))); | |
| 824 } | |
| 825 } | |
| 826 } | |
| 827 | |
| 828 | |
| 829 void IRRegExpMacroAssembler::CheckCharacter(uint32_t c, BlockLabel* on_equal) { | 788 void IRRegExpMacroAssembler::CheckCharacter(uint32_t c, BlockLabel* on_equal) { |
| 830 TAG(); | 789 TAG(); |
| 831 Definition* cur_char_def = LoadLocal(current_character_); | 790 Definition* cur_char_def = LoadLocal(current_character_); |
| 832 Definition* char_def = Uint64Constant(c); | 791 Definition* char_def = Uint64Constant(c); |
| 833 | 792 |
| 834 BranchOrBacktrack(Comparison(kEQ, cur_char_def, char_def), | 793 BranchOrBacktrack(Comparison(kEQ, cur_char_def, char_def), |
| 835 on_equal); | 794 on_equal); |
| 836 } | 795 } |
| 837 | 796 |
| 838 | 797 |
| (...skipping 1005 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1844 index, | 1803 index, |
| 1845 characters, | 1804 characters, |
| 1846 specialization_cid_, | 1805 specialization_cid_, |
| 1847 Scanner::kNoSourcePos)); | 1806 Scanner::kNoSourcePos)); |
| 1848 } | 1807 } |
| 1849 | 1808 |
| 1850 | 1809 |
| 1851 #undef __ | 1810 #undef __ |
| 1852 | 1811 |
| 1853 } // namespace dart | 1812 } // namespace dart |
| OLD | NEW |