5#if !defined(DART_PRECOMPILED_RUNTIME)
30 if (FLAG_trace_irregexp) { \
34 Print(Bind(new (Z) ConstantInstr(String::ZoneHandle( \
35 Z, Symbols::FromConcat(thread_, String::Handle(String::New("TAG: ")), \
36 String::Handle(String::New(__FUNCTION__)))))));
39 if (FLAG_trace_irregexp) { \
67 intptr_t specialization_cid,
68 intptr_t capture_count,
74 thread_(
Thread::Current()),
75 specialization_cid_(specialization_cid),
76 parsed_function_(parsed_function),
77 ic_data_array_(ic_data_array),
78 current_instruction_(nullptr),
80 stack_pointer_(nullptr),
81 current_character_(nullptr),
82 current_position_(nullptr),
83 string_param_(nullptr),
84 string_param_length_(nullptr),
85 start_index_param_(nullptr),
87 saved_registers_count_((capture_count + 1) * 2),
90 switch (specialization_cid) {
91 case kOneByteStringCid:
94 case kTwoByteStringCid:
110 start_block_ =
new (
zone)
112 success_block_ =
new (
zone)
114 backtrack_block_ =
new (
zone)
116 exit_block_ =
new (
zone)
119 GenerateEntryBlock();
120 GenerateSuccessBlock();
123 blocks_.Add(entry_block_);
125 blocks_.Add(start_block_);
126 blocks_.Add(success_block_);
127 blocks_.Add(backtrack_block_);
128 blocks_.Add(exit_block_);
131 set_current_instruction(start_block_);
136void IRRegExpMacroAssembler::InitializeLocals() {
143 stack_ = Local(Symbols::stack());
144 stack_pointer_ = Local(Symbols::stack_pointer());
145 registers_ = Local(Symbols::position_registers());
146 current_character_ = Local(Symbols::current_character());
147 current_position_ = Local(Symbols::current_position());
148 string_param_length_ = Local(Symbols::string_param_length());
149 capture_length_ = Local(Symbols::capture_length());
150 match_start_index_ = Local(Symbols::match_start_index());
151 capture_start_index_ = Local(Symbols::capture_start_index());
152 match_end_index_ = Local(Symbols::match_end_index());
153 char_in_capture_ = Local(Symbols::char_in_capture());
154 char_in_match_ = Local(Symbols::char_in_match());
155 index_temp_ = Local(Symbols::index_temp());
156 result_ = Local(Symbols::c_result());
158 string_param_ = Parameter(Symbols::string_param(),
160 start_index_param_ = Parameter(Symbols::start_index_param(),
164void IRRegExpMacroAssembler::GenerateEntryBlock() {
169 Value* string_push = PushLocal(string_param_);
171 StoreLocal(string_param_length_,
178 Value* start_index_push = PushLocal(start_index_param_);
179 Value* length_push = PushLocal(string_param_length_);
181 StoreLocal(current_position_, Bind(Sub(start_index_push, length_push)));
185 const Class& regexp_class =
186 Class::Handle(lib.LookupClassAllowPrivate(Symbols::_RegExp()));
188 Z, regexp_class.LookupFunctionAllowPrivate(Symbols::_getRegisters()));
192 num_registers_constant_instr =
194 StoreLocal(registers_, Bind(StaticCall(get_registers_function,
195 Bind(num_registers_constant_instr),
198 const Field& backtracking_stack_field =
200 Symbols::_backtrackingStack()));
201 StoreLocal(stack_, Bind(LoadStaticField(backtracking_stack_field,
206 StoreLocal(stack_pointer_, Bind(Int64Constant(-1)));
209 current_instruction_->
Goto(start_block_);
213 set_current_instruction(backtrack_block_);
215 CheckPreemption(
true);
219 Value* block_id_push = Bind(PopStack());
221 CloseBlockWith(backtrack_goto_);
224 for (intptr_t j = 0; j < entries_count; j++) {
230void IRRegExpMacroAssembler::GenerateSuccessBlock() {
231 set_current_instruction(success_block_);
236 Value*
length = Bind(Uint64Constant(saved_registers_count_));
238 length, GetNextDeoptId()));
239 StoreLocal(result_, array);
242 for (intptr_t
i = 0;
i < saved_registers_count_;
i++) {
243 Value* matches_push = PushLocal(result_);
244 Value* index_push = Bind(Uint64Constant(
i));
248 Value* offset_push = LoadRegister(
i);
249 Value* len_push = PushLocal(string_param_length_);
250 Value* value_push = Bind(Add(offset_push, len_push));
252 Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX),
253 matches_push, index_push, value_push));
257 PRINT(PushLocal(result_));
260 AppendInstruction(
new (
Z) DartReturnInstr(
261 InstructionSource(), Bind(LoadLocal(result_)), GetNextDeoptId()));
264void IRRegExpMacroAssembler::GenerateExitBlock() {
265 set_current_instruction(exit_block_);
269 AppendInstruction(
new (
Z) DartReturnInstr(
270 InstructionSource(), Bind(LoadLocal(result_)), GetNextDeoptId()));
274 ASSERT(registers_count_ >= saved_registers_count_);
276 ConstantInstr* new_constant = Int64Constant(registers_count_);
278 num_registers_constant_instr->
ReplaceWith(new_constant,
nullptr);
287 const Smi& start_offset,
304 if (retval.IsLanguageError()) {
308 if (retval.IsError()) {
317 return Array::Cast(retval).ptr();
321 intptr_t index)
const {
323 new (
Z)
LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
324 name, Object::dynamic_type());
332LocalVariable* IRRegExpMacroAssembler::Local(
const String&
name) {
333 LocalVariable*
local =
334 new (
Z) LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
335 name, Object::dynamic_type());
336 local->set_index(VariableIndex(GetNextLocalIndex()));
341ConstantInstr* IRRegExpMacroAssembler::Int64Constant(int64_t
value)
const {
346ConstantInstr* IRRegExpMacroAssembler::Uint64Constant(uint64_t
value)
const {
348 return Int64Constant(
static_cast<int64_t
>(
value));
351ConstantInstr* IRRegExpMacroAssembler::BoolConstant(
bool value)
const {
355ConstantInstr* IRRegExpMacroAssembler::StringConstant(
const char*
value)
const {
360ConstantInstr* IRRegExpMacroAssembler::WordCharacterMapConstant()
const {
362 const Class& regexp_class =
363 Class::Handle(
Z, lib.LookupClassAllowPrivate(Symbols::_RegExp()));
366 regexp_class.LookupStaticFieldAllowPrivate(Symbols::_wordCharacterMap()));
367 ASSERT(!word_character_field.IsNull());
373 if (
value.IsError()) {
380ComparisonInstr* IRRegExpMacroAssembler::Comparison(ComparisonKind kind,
384 Token::Kind intermediate_operator = Token::kILLEGAL;
387 intermediate_operator = Token::kEQ;
390 intermediate_operator = Token::kEQ;
391 strict_comparison = Token::kNE_STRICT;
394 intermediate_operator = Token::kLT;
397 intermediate_operator = Token::kGT;
400 intermediate_operator = Token::kLTE;
403 intermediate_operator = Token::kGTE;
409 ASSERT(intermediate_operator != Token::kILLEGAL);
411 Value* lhs_value = Bind(InstanceCall(
412 InstanceCallDescriptor::FromToken(intermediate_operator), lhs, rhs));
413 Value* rhs_value = Bind(BoolConstant(
true));
416 StrictCompareInstr(InstructionSource(), strict_comparison, lhs_value,
417 rhs_value,
true, GetNextDeoptId());
420ComparisonInstr* IRRegExpMacroAssembler::Comparison(ComparisonKind kind,
423 Value* lhs_push = Bind(lhs);
424 Value* rhs_push = Bind(rhs);
425 return Comparison(kind, lhs_push, rhs_push);
428StaticCallInstr* IRRegExpMacroAssembler::StaticCall(
432 return StaticCall(
function, std::move(arguments), rebind_rule);
435StaticCallInstr* IRRegExpMacroAssembler::StaticCall(
442 return StaticCall(
function, std::move(arguments), rebind_rule);
445StaticCallInstr* IRRegExpMacroAssembler::StaticCall(
454 return StaticCall(
function, std::move(arguments), rebind_rule);
457StaticCallInstr* IRRegExpMacroAssembler::StaticCall(
461 const intptr_t kTypeArgsLen = 0;
462 return new (
Z) StaticCallInstr(InstructionSource(),
function, kTypeArgsLen,
463 Object::null_array(), std::move(arguments),
464 ic_data_array_, GetNextDeoptId(), rebind_rule);
467InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall(
468 const InstanceCallDescriptor&
desc,
473 return InstanceCall(
desc, std::move(arguments));
476InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall(
477 const InstanceCallDescriptor&
desc,
484 return InstanceCall(
desc, std::move(arguments));
487InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall(
488 const InstanceCallDescriptor&
desc,
497 return InstanceCall(
desc, std::move(arguments));
500InstanceCallInstr* IRRegExpMacroAssembler::InstanceCall(
501 const InstanceCallDescriptor&
desc,
503 const intptr_t kTypeArgsLen = 0;
504 return new (
Z) InstanceCallInstr(
505 InstructionSource(),
desc.name,
desc.token_kind, std::move(arguments),
506 kTypeArgsLen, Object::null_array(),
desc.checked_argument_count,
507 ic_data_array_, GetNextDeoptId());
510LoadLocalInstr* IRRegExpMacroAssembler::LoadLocal(LocalVariable*
local)
const {
511 return new (
Z) LoadLocalInstr(*
local, InstructionSource());
514void IRRegExpMacroAssembler::StoreLocal(LocalVariable*
local,
Value*
value) {
515 Do(
new (
Z) StoreLocalInstr(*
local,
value, InstructionSource()));
518LoadStaticFieldInstr* IRRegExpMacroAssembler::LoadStaticField(
520 bool calls_initializer)
const {
521 return new (
Z) LoadStaticFieldInstr(field, InstructionSource(),
522 calls_initializer, GetNextDeoptId());
525void IRRegExpMacroAssembler::set_current_instruction(Instruction* instruction) {
526 current_instruction_ = instruction;
529Value* IRRegExpMacroAssembler::Bind(Definition* definition) {
530 AppendInstruction(definition);
531 definition->set_temp_index(temp_id_.Alloc());
533 return new (
Z)
Value(definition);
536void IRRegExpMacroAssembler::Do(Definition* definition) {
537 AppendInstruction(definition);
540Value* IRRegExpMacroAssembler::BindLoadLocal(
const LocalVariable&
local) {
542 return Bind(
new (
Z) LoadLocalInstr(
local, InstructionSource()));
549#define HANDLE_DEAD_CODE_EMISSION() \
550 if (current_instruction_ == nullptr) { \
551 if (FLAG_trace_irregexp) { \
553 "WARNING: Attempting to append to a closed assembler. " \
554 "This could be either a bug or generation of dead code " \
555 "inherited from V8.\n"); \
561void IRRegExpMacroAssembler::AppendInstruction(Instruction* instruction) {
564 ASSERT(current_instruction_ !=
nullptr);
565 ASSERT(current_instruction_->
next() ==
nullptr);
567 temp_id_.Dealloc(instruction->InputCount());
569 current_instruction_->
LinkTo(instruction);
570 set_current_instruction(instruction);
573void IRRegExpMacroAssembler::CloseBlockWith(Instruction* instruction) {
576 ASSERT(current_instruction_ !=
nullptr);
577 ASSERT(current_instruction_->
next() ==
nullptr);
579 temp_id_.Dealloc(instruction->InputCount());
581 current_instruction_->
LinkTo(instruction);
582 set_current_instruction(
nullptr);
599 ASSERT(current_instruction_ !=
nullptr);
600 ASSERT(current_instruction_->
next() ==
nullptr);
601 current_instruction_->
Goto(to);
602 set_current_instruction(
nullptr);
605Value* IRRegExpMacroAssembler::PushLocal(LocalVariable*
local) {
606 return Bind(LoadLocal(
local));
618 Do(StaticCall(print_fn, argument, ICData::kStatic));
622 for (intptr_t
i = 0;
i < blocks_.length();
i++) {
634 Value* cur_pos_push = PushLocal(current_position_);
635 Value* by_push = Bind(Int64Constant(by));
637 Value* new_pos_value = Bind(Add(cur_pos_push, by_push));
638 StoreLocal(current_position_, new_pos_value);
645 ASSERT(reg < registers_count_);
648 Value* registers_push = PushLocal(registers_);
649 Value* index_push = PushRegisterIndex(reg);
650 Value* reg_push = LoadRegister(reg);
651 Value* by_push = Bind(Int64Constant(by));
652 Value* value_push = Bind(Add(reg_push, by_push));
653 StoreRegister(registers_push, index_push, value_push);
659 GoTo(backtrack_block_);
669 label->
BindTo(block_id_.Alloc());
670 blocks_.Add(label->
block());
672 if (current_instruction_ !=
nullptr) {
675 set_current_instruction(label->
block());
681intptr_t IRRegExpMacroAssembler::GetNextLocalIndex() {
682 intptr_t
id = local_id_.Alloc();
686Value* IRRegExpMacroAssembler::LoadRegister(intptr_t index) {
687 Value* registers_push = PushLocal(registers_);
688 Value* index_push = PushRegisterIndex(index);
689 return Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX),
690 registers_push, index_push));
693void IRRegExpMacroAssembler::StoreRegister(intptr_t index, intptr_t
value) {
694 Value* registers_push = PushLocal(registers_);
695 Value* index_push = PushRegisterIndex(index);
696 Value* value_push = Bind(Uint64Constant(
value));
697 StoreRegister(registers_push, index_push, value_push);
700void IRRegExpMacroAssembler::StoreRegister(
Value* registers,
704 Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX),
705 registers, index,
value));
708Value* IRRegExpMacroAssembler::PushRegisterIndex(intptr_t index) {
709 if (registers_count_ <= index) {
710 registers_count_ = index + 1;
712 return Bind(Uint64Constant(index));
717 Definition* cur_char_def = LoadLocal(current_character_);
720 BranchOrBacktrack(Comparison(kEQ, cur_char_def, char_def), on_equal);
727 Comparison(kGT, LoadLocal(current_character_), Uint64Constant(limit)),
736 InstanceCall(InstanceCallDescriptor::FromToken(Token::kNEGATE),
737 PushLocal(string_param_length_));
738 Definition* offset_def = LoadLocal(current_position_);
739 BranchOrBacktrack(Comparison(kEQ, neg_len_def, offset_def), on_at_start);
750 Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kNEGATE),
751 PushLocal(string_param_length_)));
752 auto current_pos_def = PushLocal(current_position_);
753 auto cp_offset_def = Bind(Int64Constant(cp_offset));
754 auto offset_def = Bind(Add(current_pos_def, cp_offset_def));
755 BranchOrBacktrack(Comparison(kNE, neg_len_def, offset_def), on_not_at_start);
762 Comparison(kLT, LoadLocal(current_character_), Uint64Constant(limit)),
772 Definition* cur_pos_def = LoadLocal(current_position_);
773 BranchOrBacktrack(Comparison(kNE,
head, cur_pos_def), &fallthrough);
778 BranchOrBacktrack(
nullptr, on_equal);
789 ASSERT(start_reg + 1 <= registers_count_);
793 Value* end_push = LoadRegister(start_reg + 1);
794 Value* start_push = LoadRegister(start_reg);
795 StoreLocal(capture_length_, Bind(Sub(end_push, start_push)));
803 Comparison(kLT, LoadLocal(capture_length_), Uint64Constant(0)),
809 Comparison(kEQ, LoadLocal(capture_length_), Uint64Constant(0)),
812 Value* pos_push =
nullptr;
813 Value* len_push =
nullptr;
815 if (!read_backward) {
817 pos_push = PushLocal(current_position_);
818 len_push = PushLocal(capture_length_);
821 InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD),
827 pos_push = PushLocal(current_position_);
828 len_push = PushLocal(string_param_length_);
829 StoreLocal(match_start_index_, Bind(Add(pos_push, len_push)));
834 BranchOrBacktrack(Comparison(kLT, LoadLocal(match_start_index_),
835 LoadLocal(capture_length_)),
839 pos_push = PushLocal(match_start_index_);
840 len_push = PushLocal(capture_length_);
841 StoreLocal(match_start_index_, Bind(Sub(pos_push, len_push)));
844 pos_push = LoadRegister(start_reg);
845 len_push = PushLocal(string_param_length_);
846 StoreLocal(capture_start_index_, Bind(Add(pos_push, len_push)));
848 pos_push = PushLocal(match_start_index_);
849 len_push = PushLocal(capture_length_);
850 StoreLocal(match_end_index_, Bind(Add(pos_push, len_push)));
853 if (mode_ ==
ASCII) {
858 StoreLocal(char_in_capture_, CharacterAt(capture_start_index_));
859 StoreLocal(char_in_match_, CharacterAt(match_start_index_));
862 Comparison(kEQ, LoadLocal(char_in_capture_), LoadLocal(char_in_match_)),
866 Value* match_char_push = PushLocal(char_in_match_);
867 Value* mask_push = Bind(Uint64Constant(0x20));
870 Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kBIT_OR),
871 match_char_push, mask_push)));
876 Comparison(kLT, LoadLocal(char_in_match_), Uint64Constant(
'a')),
879 Comparison(kGT, LoadLocal(char_in_match_), Uint64Constant(
'z')),
881 GoTo(&convert_capture);
886 Comparison(kLT, LoadLocal(char_in_match_), Uint64Constant(224)),
889 Comparison(kGT, LoadLocal(char_in_match_), Uint64Constant(254)),
893 Comparison(kEQ, LoadLocal(char_in_match_), Uint64Constant(247)),
899 Value* capture_char_push = PushLocal(char_in_capture_);
900 mask_push = Bind(Uint64Constant(0x20));
903 Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kBIT_OR),
904 capture_char_push, mask_push)));
907 Comparison(kNE, LoadLocal(char_in_match_), LoadLocal(char_in_capture_)),
913 Value* index_push = PushLocal(capture_start_index_);
914 Value* inc_push = Bind(Uint64Constant(1));
915 StoreLocal(capture_start_index_, Bind(Add(index_push, inc_push)));
917 index_push = PushLocal(match_start_index_);
918 inc_push = Bind(Uint64Constant(1));
919 StoreLocal(match_start_index_, Bind(Add(index_push, inc_push)));
922 BranchOrBacktrack(Comparison(kLT, LoadLocal(match_start_index_),
923 LoadLocal(match_end_index_)),
928 Value* string_value = Bind(LoadLocal(string_param_));
929 Value* lhs_index_value = Bind(LoadLocal(match_start_index_));
930 Value* rhs_index_value = Bind(LoadLocal(capture_start_index_));
931 Value* length_value = Bind(LoadLocal(capture_length_));
936 string_value, lhs_index_value, rhs_index_value, length_value,
939 BranchOrBacktrack(Comparison(kNE, is_match_def, BoolConstant(
true)),
947 pos_push = PushLocal(current_position_);
948 len_push = PushLocal(capture_length_);
949 StoreLocal(current_position_, Bind(Sub(pos_push, len_push)));
952 Value* match_end_push = PushLocal(match_end_index_);
953 len_push = PushLocal(string_param_length_);
954 StoreLocal(current_position_, Bind(Sub(match_end_push, len_push)));
964 ASSERT(start_reg + 1 <= registers_count_);
970 Value* end_push = LoadRegister(start_reg + 1);
971 Value* start_push = LoadRegister(start_reg);
972 StoreLocal(capture_length_, Bind(Sub(end_push, start_push)));
976 Comparison(kLT, LoadLocal(capture_length_), Uint64Constant(0)),
981 Comparison(kEQ, LoadLocal(capture_length_), Uint64Constant(0)),
984 Value* pos_push =
nullptr;
985 Value* len_push =
nullptr;
987 if (!read_backward) {
989 pos_push = PushLocal(current_position_);
990 len_push = PushLocal(capture_length_);
993 InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD),
1000 pos_push = PushLocal(current_position_);
1001 len_push = PushLocal(string_param_length_);
1002 StoreLocal(match_start_index_, Bind(Add(pos_push, len_push)));
1004 if (read_backward) {
1007 BranchOrBacktrack(Comparison(kLT, LoadLocal(match_start_index_),
1008 LoadLocal(capture_length_)),
1012 pos_push = PushLocal(match_start_index_);
1013 len_push = PushLocal(capture_length_);
1014 StoreLocal(match_start_index_, Bind(Sub(pos_push, len_push)));
1017 pos_push = LoadRegister(start_reg);
1018 len_push = PushLocal(string_param_length_);
1019 StoreLocal(capture_start_index_, Bind(Add(pos_push, len_push)));
1021 pos_push = PushLocal(match_start_index_);
1022 len_push = PushLocal(capture_length_);
1023 StoreLocal(match_end_index_, Bind(Add(pos_push, len_push)));
1028 StoreLocal(char_in_capture_, CharacterAt(capture_start_index_));
1029 StoreLocal(char_in_match_, CharacterAt(match_start_index_));
1032 Comparison(kNE, LoadLocal(char_in_capture_), LoadLocal(char_in_match_)),
1036 Value* index_push = PushLocal(capture_start_index_);
1037 Value* inc_push = Bind(Uint64Constant(1));
1038 StoreLocal(capture_start_index_, Bind(Add(index_push, inc_push)));
1040 index_push = PushLocal(match_start_index_);
1041 inc_push = Bind(Uint64Constant(1));
1042 StoreLocal(match_start_index_, Bind(Add(index_push, inc_push)));
1045 BranchOrBacktrack(Comparison(kLT, LoadLocal(match_start_index_),
1046 LoadLocal(match_end_index_)),
1051 if (read_backward) {
1053 pos_push = PushLocal(current_position_);
1054 len_push = PushLocal(capture_length_);
1055 StoreLocal(current_position_, Bind(Sub(pos_push, len_push)));
1058 Value* match_end_push = PushLocal(match_end_index_);
1059 len_push = PushLocal(string_param_length_);
1060 StoreLocal(current_position_, Bind(Sub(match_end_push, len_push)));
1070 Comparison(kNE, LoadLocal(current_character_), Uint64Constant(c)),
1079 Definition* actual_def = LoadLocal(current_character_);
1081 Value* actual_push = Bind(actual_def);
1082 Value* mask_push = Bind(Uint64Constant(mask));
1083 actual_def = InstanceCall(InstanceCallDescriptor::FromToken(Token::kBIT_AND),
1084 actual_push, mask_push);
1085 Definition* expected_def = Uint64Constant(c);
1087 BranchOrBacktrack(Comparison(kEQ, actual_def, expected_def), on_equal);
1096 Definition* actual_def = LoadLocal(current_character_);
1098 Value* actual_push = Bind(actual_def);
1099 Value* mask_push = Bind(Uint64Constant(mask));
1100 actual_def = InstanceCall(InstanceCallDescriptor::FromToken(Token::kBIT_AND),
1101 actual_push, mask_push);
1102 Definition* expected_def = Uint64Constant(c);
1104 BranchOrBacktrack(Comparison(kNE, actual_def, expected_def), on_not_equal);
1115 Definition* actual_def = LoadLocal(current_character_);
1117 Value* actual_push = Bind(actual_def);
1118 Value* minus_push = Bind(Uint64Constant(minus));
1120 actual_push = Bind(Sub(actual_push, minus_push));
1121 Value* mask_push = Bind(Uint64Constant(mask));
1122 actual_def = InstanceCall(InstanceCallDescriptor::FromToken(Token::kBIT_AND),
1123 actual_push, mask_push);
1124 Definition* expected_def = Uint64Constant(c);
1126 BranchOrBacktrack(Comparison(kNE, actual_def, expected_def), on_not_equal);
1140 Comparison(kLT, LoadLocal(current_character_), Uint64Constant(from)),
1143 Comparison(kGT, LoadLocal(current_character_), Uint64Constant(to)),
1145 BranchOrBacktrack(
nullptr, on_in_range);
1158 Comparison(kLT, LoadLocal(current_character_), Uint64Constant(from)),
1162 Comparison(kGT, LoadLocal(current_character_), Uint64Constant(to)),
1171 Value* index_push = PushLocal(current_character_);
1176 Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kBIT_AND),
1177 index_push, mask_push));
1181 InstanceCallDescriptor::FromToken(Token::kINDEX), table_push, index_push);
1184 BranchOrBacktrack(Comparison(kNE, byte_def, zero_def), on_bit_set);
1197 if (mode_ ==
ASCII) {
1202 Comparison(kEQ, LoadLocal(current_character_), Uint64Constant(
' ')),
1207 BranchOrBacktrack(Comparison(kNE, LoadLocal(current_character_),
1208 Uint64Constant(0x00a0)),
1228 Comparison(kEQ, LoadLocal(current_character_), Uint64Constant(
'\n')),
1231 Comparison(kEQ, LoadLocal(current_character_), Uint64Constant(
'\r')),
1233 if (mode_ ==
UC16) {
1234 BranchOrBacktrack(Comparison(kEQ, LoadLocal(current_character_),
1235 Uint64Constant(0x2028)),
1237 BranchOrBacktrack(Comparison(kEQ, LoadLocal(current_character_),
1238 Uint64Constant(0x2029)),
1244 if (mode_ !=
ASCII) {
1247 Comparison(kGT, LoadLocal(current_character_), Uint64Constant(
'z')),
1251 Value* table_push = Bind(WordCharacterMapConstant());
1252 Value* index_push = PushLocal(current_character_);
1255 InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX),
1256 table_push, index_push);
1259 BranchOrBacktrack(Comparison(kEQ, byte_def, zero_def), on_no_match);
1265 if (mode_ !=
ASCII) {
1268 Comparison(kGT, LoadLocal(current_character_), Uint64Constant(
'z')),
1274 Value* table_push = Bind(WordCharacterMapConstant());
1275 Value* index_push = PushLocal(current_character_);
1278 InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX),
1279 table_push, index_push);
1282 BranchOrBacktrack(Comparison(kNE, byte_def, zero_def), on_no_match);
1284 if (mode_ !=
ASCII) {
1298 Comparison(kEQ, LoadLocal(current_character_), Uint64Constant(
'\n')),
1301 Comparison(kEQ, LoadLocal(current_character_), Uint64Constant(
'\r')),
1303 if (mode_ ==
UC16) {
1304 BranchOrBacktrack(Comparison(kEQ, LoadLocal(current_character_),
1305 Uint64Constant(0x2028)),
1307 BranchOrBacktrack(Comparison(kEQ, LoadLocal(current_character_),
1308 Uint64Constant(0x2029)),
1311 BranchOrBacktrack(
nullptr, on_no_match);
1334 Value* reg_push = LoadRegister(reg);
1335 Value*
pos = Bind(Int64Constant(comparand));
1336 BranchOrBacktrack(Comparison(kGTE, reg_push,
pos), if_ge);
1343 Value* reg_push = LoadRegister(reg);
1344 Value*
pos = Bind(Int64Constant(comparand));
1345 BranchOrBacktrack(Comparison(kLT, reg_push,
pos), if_lt);
1350 Value* reg_push = LoadRegister(reg);
1351 Value*
pos = Bind(LoadLocal(current_position_));
1352 BranchOrBacktrack(Comparison(kEQ, reg_push,
pos), if_eq);
1363 intptr_t characters) {
1365 ASSERT(cp_offset < (1 << 30));
1367 if (cp_offset >= 0) {
1373 LoadCurrentCharacterUnchecked(cp_offset, characters);
1378 StoreLocal(current_position_, Bind(PopStack()));
1383 ASSERT(reg < registers_count_);
1384 Value* registers_push = PushLocal(registers_);
1385 Value* index_push = PushRegisterIndex(reg);
1386 Value* pop_push = Bind(PopStack());
1387 StoreRegister(registers_push, index_push, pop_push);
1390void IRRegExpMacroAssembler::PushStack(
Definition* definition) {
1391 Value* stack_push = PushLocal(stack_);
1392 Value* stack_pointer_push = PushLocal(stack_pointer_);
1393 StoreLocal(stack_pointer_,
1394 Bind(Add(stack_pointer_push, Bind(Uint64Constant(1)))));
1395 stack_pointer_push = PushLocal(stack_pointer_);
1397 Value* value_push = Bind(definition);
1398 Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX),
1399 stack_push, stack_pointer_push, value_push));
1402Definition* IRRegExpMacroAssembler::PopStack() {
1403 Value* stack_push = PushLocal(stack_);
1404 Value* stack_pointer_push1 = PushLocal(stack_pointer_);
1405 Value* stack_pointer_push2 = PushLocal(stack_pointer_);
1406 StoreLocal(stack_pointer_,
1407 Bind(Sub(stack_pointer_push2, Bind(Uint64Constant(1)))));
1408 return InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX),
1409 stack_push, stack_pointer_push1);
1412Definition* IRRegExpMacroAssembler::PeekStack() {
1413 Value* stack_push = PushLocal(stack_);
1414 Value* stack_pointer_push = PushLocal(stack_pointer_);
1415 return InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX),
1416 stack_push, stack_pointer_push);
1438 PushStack(LoadLocal(current_position_));
1444 Value* stack_push = PushLocal(stack_);
1445 Value* stack_pointer_push = PushLocal(stack_pointer_);
1446 StoreLocal(stack_pointer_,
1447 Bind(Add(stack_pointer_push, Bind(Uint64Constant(1)))));
1448 stack_pointer_push = PushLocal(stack_pointer_);
1450 Value* value_push = LoadRegister(reg);
1451 Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX),
1452 stack_push, stack_pointer_push, value_push));
1460void IRRegExpMacroAssembler::CheckStackLimit() {
1462 Value* stack_push = PushLocal(stack_);
1463 Value* length_push =
1467 Value* capacity_push =
1469 Value* stack_pointer_push = PushLocal(stack_pointer_);
1471 Comparison(kGT, capacity_push, stack_pointer_push), GetNextDeoptId());
1472 CloseBlockWith(branch);
1485void IRRegExpMacroAssembler::GrowStack() {
1488 const Class& regexp_class =
1489 Class::Handle(lib.LookupClassAllowPrivate(Symbols::_RegExp()));
1491 const Function& grow_backtracking_stack_function =
1493 Symbols::_growBacktrackingStack()));
1494 StoreLocal(stack_, Bind(StaticCall(grow_backtracking_stack_function,
1500 StoreLocal(current_position_, LoadRegister(reg));
1506 ASSERT(reg < registers_count_);
1507 StoreLocal(stack_pointer_, LoadRegister(reg));
1515 Definition* cur_pos_def = LoadLocal(current_position_);
1516 Definition* by_value_def = Int64Constant(-by);
1518 BranchOrBacktrack(Comparison(kGTE, cur_pos_def, by_value_def),
1521 StoreLocal(current_position_, Bind(Int64Constant(-by)));
1526 LoadCurrentCharacterUnchecked(-1, 1);
1534 ASSERT(reg >= saved_registers_count_);
1535 StoreRegister(reg, to);
1540 GoTo(success_block_);
1546 intptr_t cp_offset) {
1549 Value* registers_push = PushLocal(registers_);
1550 Value* index_push = PushRegisterIndex(reg);
1551 Value* pos_push = PushLocal(current_position_);
1552 Value* off_push = Bind(Int64Constant(cp_offset));
1553 Value* neg_off_push = Bind(Add(pos_push, off_push));
1556 StoreRegister(registers_push, index_push, neg_off_push);
1563 ASSERT(reg_from <= reg_to);
1568 for (intptr_t reg = reg_from; reg <= reg_to; reg++) {
1569 Value* registers_push = PushLocal(registers_);
1570 Value* index_push = PushRegisterIndex(reg);
1571 Value* minus_one_push = Bind(Int64Constant(-1));
1572 Value* length_push = PushLocal(string_param_length_);
1573 Value* value_push = Bind(Sub(minus_one_push, length_push));
1574 StoreRegister(registers_push, index_push, value_push);
1581 Value* registers_push = PushLocal(registers_);
1582 Value* index_push = PushRegisterIndex(reg);
1583 Value* tip_push = PushLocal(stack_pointer_);
1584 StoreRegister(registers_push, index_push, tip_push);
1592 if (cp_offset >= 0) {
1593 Definition* curpos_def = LoadLocal(current_position_);
1594 Definition* cp_off_def = Int64Constant(-cp_offset);
1598 BranchOrBacktrack(Comparison(kGTE, curpos_def, cp_off_def),
1604 Value* pos_push = PushLocal(current_position_);
1605 Value* len_push = PushLocal(string_param_length_);
1607 Comparison(kLT, Add(pos_push, len_push), Uint64Constant(-cp_offset)),
1612void IRRegExpMacroAssembler::BranchOrBacktrack(
ComparisonInstr* comparison,
1614 if (comparison ==
nullptr) {
1615 if (true_successor ==
nullptr) {
1619 GoTo(true_successor);
1624 JoinEntryInstr* true_successor_block = backtrack_block_;
1625 if (true_successor !=
nullptr) {
1627 true_successor_block = true_successor->
block();
1629 ASSERT(true_successor_block !=
nullptr);
1632 BlockLabel fallthrough;
1634 BranchInstr* branch =
new (
Z) BranchInstr(comparison, GetNextDeoptId());
1636 *branch->false_successor_address() = TargetWithJoinGoto(fallthrough.block());
1638 CloseBlockWith(branch);
1642TargetEntryInstr* IRRegExpMacroAssembler::TargetWithJoinGoto(
1643 JoinEntryInstr*
dst) {
1644 TargetEntryInstr*
target =
new (
Z)
1648 target->AppendInstruction(
new (
Z) GotoInstr(
dst, GetNextDeoptId()));
1653IndirectEntryInstr* IRRegExpMacroAssembler::IndirectWithJoinGoto(
1654 JoinEntryInstr*
dst) {
1655 IndirectEntryInstr*
target =
1656 new (
Z) IndirectEntryInstr(block_id_.Alloc(), indirect_id_.Alloc(),
1660 target->AppendInstruction(
new (
Z) GotoInstr(
dst, GetNextDeoptId()));
1665void IRRegExpMacroAssembler::CheckPreemption(
bool is_backtrack) {
1671 AppendInstruction(
new (
Z) CheckStackOverflowInstr(
1672 InstructionSource(),
1674 1, GetNextDeoptId(),
1679Definition* IRRegExpMacroAssembler::Add(
Value* lhs,
Value* rhs) {
1680 return InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD), lhs, rhs);
1683Definition* IRRegExpMacroAssembler::Sub(
Value* lhs,
Value* rhs) {
1684 return InstanceCall(InstanceCallDescriptor::FromToken(Token::kSUB), lhs, rhs);
1687void IRRegExpMacroAssembler::LoadCurrentCharacterUnchecked(
1689 intptr_t characters) {
1693 if (mode_ ==
ASCII) {
1694 ASSERT(characters == 1 || characters == 2 || characters == 4);
1697 ASSERT(characters == 1 || characters == 2);
1703 Value* off_arg = Bind(Int64Constant(cp_offset));
1704 Value* pos_arg = BindLoadLocal(*current_position_);
1705 Value* off_pos_arg = Bind(Add(off_arg, pos_arg));
1706 Value* len_arg = BindLoadLocal(*string_param_length_);
1708 StoreLocal(index_temp_, Bind(Add(off_pos_arg, len_arg)));
1711 Value* code_unit_value = LoadCodeUnitsAt(index_temp_, characters);
1712 StoreLocal(current_character_, code_unit_value);
1713 PRINT(PushLocal(current_character_));
1716Value* IRRegExpMacroAssembler::CharacterAt(LocalVariable* index) {
1717 return LoadCodeUnitsAt(index, 1);
1720Value* IRRegExpMacroAssembler::LoadCodeUnitsAt(LocalVariable* index,
1721 intptr_t characters) {
1723 Value* pattern_val = BindLoadLocal(*string_param_);
1726 Value* index_val = BindLoadLocal(*index);
1729 LoadCodeUnitsInstr(pattern_val, index_val, characters,
1730 specialization_cid_, InstructionSource()));
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
void check_bounds(skiatest::Reporter *reporter, const SkPath &path)
#define DEBUG_ASSERT(cond)
static ArrayPtr New(intptr_t len, Heap::Space space=Heap::kNew)
intptr_t block_id() const
Convenience wrapper around a BlockEntryInstr pointer.
void BindTo(intptr_t pos)
JoinEntryInstr * block() const
static const Bool & False()
static const Bool & True()
TargetEntryInstr ** false_successor_address()
TargetEntryInstr ** true_successor_address()
static ObjectPtr InvokeFunction(const Function &function, const Array &arguments)
void ReplaceWith(Definition *other, ForwardInstructionIterator *iterator)
void set_temp_index(intptr_t index)
intptr_t temp_index() const
static DART_NORETURN void ThrowCompileTimeError(const LanguageError &error)
static DART_NORETURN void PropagateError(const Error &error)
static StringPtr GetterSymbol(const String &field_name)
static void PrintBlock(BlockEntryInstr *block, bool print_locations)
FunctionEntryInstr * normal_entry() const
void AddIndirectEntry(IndirectEntryInstr *entry)
void set_normal_entry(FunctionEntryInstr *entry)
const GrowableArray< IndirectEntryInstr * > & indirect_entries() const
virtual void CheckNotCharacter(uint32_t c, BlockLabel *on_not_equal)
virtual void CheckCharacterNotInRange(uint16_t from, uint16_t to, BlockLabel *on_not_in_range)
virtual void PopCurrentPosition()
void FinalizeRegistersArray()
virtual void CheckCharacterInRange(uint16_t from, uint16_t to, BlockLabel *on_in_range)
virtual void BindBlock(BlockLabel *label)
virtual void CheckCharacterGT(uint16_t limit, BlockLabel *on_greater)
virtual void IfRegisterLT(intptr_t reg, intptr_t comparand, BlockLabel *if_lt)
void GenerateBacktrackBlock()
virtual void IfRegisterGE(intptr_t reg, intptr_t comparand, BlockLabel *if_ge)
IRRegExpMacroAssembler(intptr_t specialization_cid, intptr_t capture_count, const ParsedFunction *parsed_function, const ZoneGrowableArray< const ICData * > &ic_data_array, intptr_t osr_id, Zone *zone)
virtual void SetRegister(intptr_t register_index, intptr_t to)
virtual void CheckAtStart(BlockLabel *on_at_start)
virtual void CheckCharacterLT(uint16_t limit, BlockLabel *on_less)
virtual void GoTo(BlockLabel *to)
virtual IrregexpImplementation Implementation()
virtual void CheckNotAtStart(intptr_t cp_offset, BlockLabel *on_not_at_start)
virtual void Print(const char *str)
virtual void CheckGreedyLoop(BlockLabel *on_tos_equals_current_position)
static ArrayPtr Execute(const RegExp ®exp, const String &input, const Smi &start_offset, bool sticky, Zone *zone)
virtual void ClearRegisters(intptr_t reg_from, intptr_t reg_to)
virtual void AdvanceCurrentPosition(intptr_t by)
virtual void CheckCharacterAfterAnd(uint32_t c, uint32_t mask, BlockLabel *on_equal)
virtual void PrintBlocks()
virtual void IfRegisterEqPos(intptr_t reg, BlockLabel *if_eq)
virtual bool CanReadUnaligned()
virtual void AdvanceRegister(intptr_t reg, intptr_t by)
virtual void PushRegister(intptr_t register_index)
virtual void CheckNotCharacterAfterAnd(uint32_t c, uint32_t mask, BlockLabel *on_not_equal)
virtual void CheckCharacter(uint32_t c, BlockLabel *on_equal)
virtual void ReadCurrentPositionFromRegister(intptr_t reg)
virtual void CheckNotCharacterAfterMinusAnd(uint16_t c, uint16_t minus, uint16_t mask, BlockLabel *on_not_equal)
virtual void CheckPosition(intptr_t cp_offset, BlockLabel *on_outside_input)
virtual ~IRRegExpMacroAssembler()
virtual void SetCurrentPositionFromEnd(intptr_t by)
virtual void CheckNotBackReference(intptr_t start_reg, bool read_backward, BlockLabel *on_no_match)
virtual void ReadStackPointerFromRegister(intptr_t reg)
virtual bool CheckSpecialCharacterClass(uint16_t type, BlockLabel *on_no_match)
virtual void CheckBitInTable(const TypedData &table, BlockLabel *on_bit_set)
virtual void PushCurrentPosition()
virtual void LoadCurrentCharacter(intptr_t cp_offset, BlockLabel *on_end_of_input, bool check_bounds=true, intptr_t characters=1)
virtual void WriteStackPointerToRegister(intptr_t reg)
virtual intptr_t stack_limit_slack()
virtual void PushBacktrack(BlockLabel *label)
virtual void CheckNotBackReferenceIgnoreCase(intptr_t start_reg, bool read_backward, bool unicode, BlockLabel *on_no_match)
virtual void WriteCurrentPositionToRegister(intptr_t reg, intptr_t cp_offset)
virtual void PopRegister(intptr_t register_index)
intptr_t indirect_id() const
void AddSuccessor(TargetEntryInstr *successor)
Instruction * next() const
void LinkTo(Instruction *next)
void Goto(JoinEntryInstr *entry)
static IntegerPtr NewCanonical(const String &str)
static IsolateGroup * Current()
static LibraryPtr CoreLibrary()
FunctionPtr LookupFunctionAllowPrivate(const String &name) const
void set_index(VariableIndex index)
intptr_t GetClassId() const
static ObjectPtr RawCast(ObjectPtr obj)
static Object & ZoneHandle()
LocalVariable * current_context_var() const
static constexpr intptr_t kTableMask
static constexpr intptr_t kTableSize
FunctionPtr function(intptr_t cid, bool sticky) const
static DART_NORETURN void LongJump(const Error &error)
static StringPtr New(const char *cstr, Heap::Space space=Heap::kNew)
static Thread * Current()
static constexpr int32_t kMaxCodeUnit
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
Dart_NativeFunction function
constexpr int64_t kMaxInt64
GrowableArray< Value * > InputsArray
static constexpr intptr_t kInvalidTryIndex
def print(*args, **kwargs)
#define HANDLE_DEAD_CODE_EMISSION()