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 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
606 | 606 |
607 Value* IRRegExpMacroAssembler::BindLoadLocal(const LocalVariable& local) { | 607 Value* IRRegExpMacroAssembler::BindLoadLocal(const LocalVariable& local) { |
608 if (local.IsConst()) { | 608 if (local.IsConst()) { |
609 return Bind(new(I) ConstantInstr(*local.ConstValue())); | 609 return Bind(new(I) ConstantInstr(*local.ConstValue())); |
610 } | 610 } |
611 ASSERT(!local.is_captured()); | 611 ASSERT(!local.is_captured()); |
612 return Bind(new(I) LoadLocalInstr(local)); | 612 return Bind(new(I) LoadLocalInstr(local)); |
613 } | 613 } |
614 | 614 |
615 | 615 |
| 616 Value* IRRegExpMacroAssembler::BindUntaggedExternalString( |
| 617 const LocalVariable& str) { |
| 618 Value* str_val = BindLoadLocal(str); |
| 619 if (!RawObject::IsExternalStringClassId(specialization_cid_)) { |
| 620 return str_val; |
| 621 } |
| 622 // The data of an external string is stored through two indirections. |
| 623 intptr_t external_offset; |
| 624 intptr_t data_offset; |
| 625 if (specialization_cid_ == kExternalOneByteStringCid) { |
| 626 external_offset = RawExternalOneByteString::data_offset(); |
| 627 data_offset = RawExternalOneByteString::ExternalData::data_offset(); |
| 628 } else if (specialization_cid_ == kExternalTwoByteStringCid) { |
| 629 external_offset = RawExternalTwoByteString::data_offset(); |
| 630 data_offset = RawExternalTwoByteString::ExternalData::data_offset(); |
| 631 } else { |
| 632 UNREACHABLE(); |
| 633 } |
| 634 Value* external_val = |
| 635 Bind(new(I) LoadUntaggedInstr(str_val, external_offset)); |
| 636 Value* data_val = |
| 637 Bind(new(I) LoadUntaggedInstr(external_val, data_offset)); |
| 638 return data_val; |
| 639 } |
| 640 |
| 641 |
616 // In some cases, the V8 irregexp engine generates unreachable code by emitting | 642 // In some cases, the V8 irregexp engine generates unreachable code by emitting |
617 // a jmp not followed by a bind. We cannot do the same, since it is impossible | 643 // a jmp not followed by a bind. We cannot do the same, since it is impossible |
618 // to append to a block following a jmp. In such cases, assume that we are doing | 644 // to append to a block following a jmp. In such cases, assume that we are doing |
619 // the correct thing, but output a warning when tracing. | 645 // the correct thing, but output a warning when tracing. |
620 #define HANDLE_DEAD_CODE_EMISSION() \ | 646 #define HANDLE_DEAD_CODE_EMISSION() \ |
621 if (current_instruction_ == NULL) { \ | 647 if (current_instruction_ == NULL) { \ |
622 if (FLAG_trace_irregexp) { \ | 648 if (FLAG_trace_irregexp) { \ |
623 OS::Print("WARNING: Attempting to append to a closed assembler. " \ | 649 OS::Print("WARNING: Attempting to append to a closed assembler. " \ |
624 "This could be either a bug or generation of dead code " \ | 650 "This could be either a bug or generation of dead code " \ |
625 "inherited from V8.\n"); \ | 651 "inherited from V8.\n"); \ |
(...skipping 1133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1759 | 1785 |
1760 ASSERT(characters == 1 || CanReadUnaligned()); | 1786 ASSERT(characters == 1 || CanReadUnaligned()); |
1761 if (mode_ == ASCII) { | 1787 if (mode_ == ASCII) { |
1762 ASSERT(characters == 1 || characters == 2 || characters == 4); | 1788 ASSERT(characters == 1 || characters == 2 || characters == 4); |
1763 } else { | 1789 } else { |
1764 ASSERT(mode_ == UC16); | 1790 ASSERT(mode_ == UC16); |
1765 ASSERT(characters == 1 || characters == 2); | 1791 ASSERT(characters == 1 || characters == 2); |
1766 } | 1792 } |
1767 | 1793 |
1768 // Bind the pattern as the load receiver. | 1794 // Bind the pattern as the load receiver. |
1769 Value* pattern = BindLoadLocal(*string_param_); | 1795 Value* pattern = BindUntaggedExternalString(*string_param_); |
1770 | 1796 |
1771 // Calculate the addressed string index as: | 1797 // Calculate the addressed string index as: |
1772 // cp_offset + current_position_ + string_param_length_ | 1798 // cp_offset + current_position_ + string_param_length_ |
1773 // TODO(zerny): Avoid generating 'add' instance-calls here. | 1799 // TODO(zerny): Avoid generating 'add' instance-calls here. |
1774 PushArgumentInstr* off_arg = | 1800 PushArgumentInstr* off_arg = |
1775 PushArgument(Bind(Int64Constant(cp_offset))); | 1801 PushArgument(Bind(Int64Constant(cp_offset))); |
1776 PushArgumentInstr* pos_arg = | 1802 PushArgumentInstr* pos_arg = |
1777 PushArgument(BindLoadLocal(*current_position_)); | 1803 PushArgument(BindLoadLocal(*current_position_)); |
1778 PushArgumentInstr* off_pos_arg = | 1804 PushArgumentInstr* off_pos_arg = |
1779 PushArgument(Bind(Add(off_arg, pos_arg))); | 1805 PushArgument(Bind(Add(off_arg, pos_arg))); |
1780 PushArgumentInstr* len_arg = | 1806 PushArgumentInstr* len_arg = |
1781 PushArgument(BindLoadLocal(*string_param_length_)); | 1807 PushArgument(BindLoadLocal(*string_param_length_)); |
1782 Value* index = Bind(Add(off_pos_arg, len_arg)); | 1808 Value* index = Bind(Add(off_pos_arg, len_arg)); |
1783 | 1809 |
1784 // Load and store the code units. | 1810 // Load and store the code units. |
1785 Value* code_unit_value = LoadCodeUnitsAt(pattern, index, characters); | 1811 Value* code_unit_value = LoadCodeUnitsAt(pattern, index, characters); |
1786 StoreLocal(current_character_, code_unit_value); | 1812 StoreLocal(current_character_, code_unit_value); |
1787 PRINT(PushLocal(current_character_)); | 1813 PRINT(PushLocal(current_character_)); |
1788 } | 1814 } |
1789 | 1815 |
1790 | 1816 |
1791 Value* IRRegExpMacroAssembler::CharacterAt(Definition* index) { | 1817 Value* IRRegExpMacroAssembler::CharacterAt(Definition* index) { |
1792 Value* pattern_val = BindLoadLocal(*string_param_); | 1818 Value* pattern_val = BindUntaggedExternalString(*string_param_); |
1793 Value* index_val = Bind(index); | 1819 Value* index_val = Bind(index); |
1794 return LoadCodeUnitsAt(pattern_val, index_val, 1); | 1820 return LoadCodeUnitsAt(pattern_val, index_val, 1); |
1795 } | 1821 } |
1796 | 1822 |
1797 | 1823 |
1798 // Note: We can't replace pattern with a load-local of string_param_ | 1824 // Note: We can't replace pattern with a load-local of string_param_ |
1799 // because we need to maintain the stack discipline in unoptimized code. | 1825 // because we need to maintain the stack discipline in unoptimized code. |
1800 Value* IRRegExpMacroAssembler::LoadCodeUnitsAt(Value* pattern, | 1826 Value* IRRegExpMacroAssembler::LoadCodeUnitsAt(Value* pattern, |
1801 Value* index, | 1827 Value* index, |
1802 intptr_t characters) { | 1828 intptr_t characters) { |
1803 return Bind(new(I) LoadCodeUnitsInstr( | 1829 return Bind(new(I) LoadCodeUnitsInstr( |
1804 pattern, | 1830 pattern, |
1805 index, | 1831 index, |
1806 characters, | 1832 characters, |
1807 specialization_cid_, | 1833 specialization_cid_, |
1808 Scanner::kNoSourcePos)); | 1834 Scanner::kNoSourcePos)); |
1809 } | 1835 } |
1810 | 1836 |
1811 | 1837 |
1812 #undef __ | 1838 #undef __ |
1813 | 1839 |
1814 } // namespace dart | 1840 } // namespace dart |
OLD | NEW |