81#define __ ACCESS_MASM(masm_)
87 int registers_to_save)
88 : NativeRegExpMacroAssembler(isolate, zone),
89 masm_(
std::make_unique<MacroAssembler>(
92 no_root_array_scope_(
masm_.get()),
94 num_registers_(registers_to_save),
95 num_saved_registers_(registers_to_save),
102 __ jmp(&entry_label_);
103 __ bind(&start_label_);
106RegExpMacroAssemblerIA32::~RegExpMacroAssemblerIA32() {
108 entry_label_.Unuse();
109 start_label_.Unuse();
110 success_label_.Unuse();
111 backtrack_label_.Unuse();
113 check_preempt_label_.Unuse();
114 stack_overflow_label_.Unuse();
115 fallback_label_.Unuse();
118int RegExpMacroAssemblerIA32::stack_limit_slack_slot_count() {
119 return RegExpStack::kStackLimitSlackSlotCount;
122void RegExpMacroAssemblerIA32::AdvanceCurrentPosition(
int by) {
124 __ add(edi, Immediate(by * char_size()));
129void RegExpMacroAssemblerIA32::AdvanceRegister(
int reg,
int by) {
133 __ add(register_location(
reg), Immediate(by));
138void RegExpMacroAssemblerIA32::Backtrack() {
140 if (has_backtrack_limit()) {
142 __ inc(Operand(ebp, kBacktrackCountOffset));
143 __ cmp(Operand(ebp, kBacktrackCountOffset), Immediate(backtrack_limit()));
144 __ j(not_equal, &next);
147 if (can_fallback()) {
148 __ jmp(&fallback_label_);
159 __ add(ebx, Immediate(
masm_->CodeObject()));
164void RegExpMacroAssemblerIA32::Bind(Label*
label) {
169void RegExpMacroAssemblerIA32::CheckCharacter(uint32_t c, Label* on_equal) {
170 __ cmp(current_character(), c);
171 BranchOrBacktrack(equal, on_equal);
174void RegExpMacroAssemblerIA32::CheckCharacterGT(base::uc16 limit,
176 __ cmp(current_character(), limit);
177 BranchOrBacktrack(greater, on_greater);
180void RegExpMacroAssemblerIA32::CheckAtStart(
int cp_offset, Label* on_at_start) {
181 __ lea(eax, Operand(edi, -char_size() + cp_offset * char_size()));
182 __ cmp(eax, Operand(ebp, kStringStartMinusOneOffset));
183 BranchOrBacktrack(equal, on_at_start);
186void RegExpMacroAssemblerIA32::CheckNotAtStart(
int cp_offset,
187 Label* on_not_at_start) {
188 __ lea(eax, Operand(edi, -char_size() + cp_offset * char_size()));
189 __ cmp(eax, Operand(ebp, kStringStartMinusOneOffset));
190 BranchOrBacktrack(not_equal, on_not_at_start);
193void RegExpMacroAssemblerIA32::CheckCharacterLT(base::uc16 limit,
195 __ cmp(current_character(), limit);
196 BranchOrBacktrack(less, on_less);
199void RegExpMacroAssemblerIA32::CheckGreedyLoop(Label* on_equal) {
201 __ cmp(edi, Operand(backtrack_stackpointer(), 0));
202 __ j(not_equal, &fallthrough);
203 __ add(backtrack_stackpointer(), Immediate(kSystemPointerSize));
204 BranchOrBacktrack(on_equal);
205 __ bind(&fallthrough);
208void RegExpMacroAssemblerIA32::CallCFunctionFromIrregexpCode(
209 ExternalReference function,
int num_arguments) {
223void RegExpMacroAssemblerIA32::PushCallerSavedRegisters() {
224 static_assert(backtrack_stackpointer() == ecx);
225 static_assert(current_character() == edx);
230void RegExpMacroAssemblerIA32::PopCallerSavedRegisters() {
235void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase(
236 int start_reg,
bool read_backward,
bool unicode, Label* on_no_match) {
238 __ mov(edx, register_location(start_reg));
239 __ mov(ebx, register_location(start_reg + 1));
245 __ j(equal, &fallthrough);
249 __ mov(eax, Operand(ebp, kStringStartMinusOneOffset));
252 BranchOrBacktrack(less_equal, on_no_match);
256 BranchOrBacktrack(greater, on_no_match);
259 if (
mode_ == LATIN1) {
262 Label loop_increment;
265 __ push(backtrack_stackpointer());
277 __ movzx_b(eax, Operand(edi, 0));
278 __ cmpb_al(Operand(edx, 0));
279 __ j(equal, &loop_increment);
283 __ lea(ecx, Operand(eax, -
'a'));
284 __ cmp(ecx,
static_cast<int32_t>(
'z' -
'a'));
285 Label convert_capture;
286 __ j(below_equal, &convert_capture);
288 __ sub(ecx, Immediate(224 -
'a'));
289 __ cmp(ecx, Immediate(254 - 224));
291 __ cmp(ecx, Immediate(247 - 224));
293 __ bind(&convert_capture);
295 __ movzx_b(ecx, Operand(edx, 0));
299 __ j(not_equal, &fail);
301 __ bind(&loop_increment);
303 __ add(edx, Immediate(1));
304 __ add(edi, Immediate(1));
312 __ pop(backtrack_stackpointer());
314 BranchOrBacktrack(on_no_match);
318 __ pop(backtrack_stackpointer());
320 __ add(esp, Immediate(kSystemPointerSize));
325 __ add(edi, register_location(start_reg));
326 __ sub(edi, register_location(start_reg + 1));
333 __ push(backtrack_stackpointer());
336 static const int argument_count = 4;
337 __ PrepareCallCFunction(argument_count, ecx);
346 __ mov(Operand(esp, 3 * kSystemPointerSize),
347 Immediate(ExternalReference::isolate_address(
isolate())));
349 __ mov(Operand(esp, 2 * kSystemPointerSize), ebx);
357 __ mov(Operand(esp, 1 * kSystemPointerSize), edi);
361 __ mov(Operand(esp, 0 * kSystemPointerSize), edx);
364 AllowExternalCallThatCantCauseGC scope(
masm_.get());
367 ? ExternalReference::re_case_insensitive_compare_unicode()
368 : ExternalReference::re_case_insensitive_compare_non_unicode();
369 CallCFunctionFromIrregexpCode(
compare, argument_count);
373 __ pop(backtrack_stackpointer());
379 BranchOrBacktrack(zero, on_no_match);
387 __ bind(&fallthrough);
390void RegExpMacroAssemblerIA32::CheckNotBackReference(
int start_reg,
392 Label* on_no_match) {
398 __ mov(edx, register_location(start_reg));
399 __ mov(eax, register_location(start_reg + 1));
405 __ j(equal, &fallthrough);
409 __ mov(ebx, Operand(ebp, kStringStartMinusOneOffset));
412 BranchOrBacktrack(less_equal, on_no_match);
416 BranchOrBacktrack(greater, on_no_match);
420 __ push(backtrack_stackpointer());
424 __ lea(ebx, Operand(esi, edi, times_1, 0));
428 __ lea(ecx, Operand(eax, ebx, times_1, 0));
432 if (
mode_ == LATIN1) {
433 __ movzx_b(eax, Operand(edx, 0));
434 __ cmpb_al(Operand(ebx, 0));
437 __ movzx_w(eax, Operand(edx, 0));
438 __ cmpw_ax(Operand(ebx, 0));
440 __ j(not_equal, &fail);
442 __ add(edx, Immediate(char_size()));
443 __ add(ebx, Immediate(char_size()));
451 __ pop(backtrack_stackpointer());
452 BranchOrBacktrack(on_no_match);
460 __ add(edi, register_location(start_reg));
461 __ sub(edi, register_location(start_reg + 1));
464 __ pop(backtrack_stackpointer());
466 __ bind(&fallthrough);
470void RegExpMacroAssemblerIA32::CheckNotCharacter(uint32_t c,
471 Label* on_not_equal) {
472 __ cmp(current_character(), c);
473 BranchOrBacktrack(not_equal, on_not_equal);
477void RegExpMacroAssemblerIA32::CheckCharacterAfterAnd(uint32_t c,
481 __ test(current_character(), Immediate(
mask));
484 __ and_(eax, current_character());
487 BranchOrBacktrack(equal, on_equal);
491void RegExpMacroAssemblerIA32::CheckNotCharacterAfterAnd(uint32_t c,
493 Label* on_not_equal) {
495 __ test(current_character(), Immediate(
mask));
498 __ and_(eax, current_character());
501 BranchOrBacktrack(not_equal, on_not_equal);
504void RegExpMacroAssemblerIA32::CheckNotCharacterAfterMinusAnd(
505 base::uc16 c, base::uc16 minus, base::uc16
mask, Label* on_not_equal) {
506 DCHECK_GT(String::kMaxUtf16CodeUnit, minus);
507 __ lea(eax, Operand(current_character(), -minus));
514 BranchOrBacktrack(not_equal, on_not_equal);
517void RegExpMacroAssemblerIA32::CheckCharacterInRange(base::uc16 from,
519 Label* on_in_range) {
520 __ lea(eax, Operand(current_character(), -from));
521 __ cmp(eax, to - from);
522 BranchOrBacktrack(below_equal, on_in_range);
525void RegExpMacroAssemblerIA32::CheckCharacterNotInRange(
526 base::uc16 from, base::uc16 to, Label* on_not_in_range) {
527 __ lea(eax, Operand(current_character(), -from));
528 __ cmp(eax, to - from);
529 BranchOrBacktrack(above, on_not_in_range);
532void RegExpMacroAssemblerIA32::CallIsCharacterInRangeArray(
533 const ZoneList<CharacterRange>* ranges) {
534 PushCallerSavedRegisters();
536 static const int kNumArguments = 2;
537 __ PrepareCallCFunction(kNumArguments, ecx);
539 __ mov(Operand(esp, 0 * kSystemPointerSize), current_character());
540 __ mov(Operand(esp, 1 * kSystemPointerSize), GetOrAddRangeArray(ranges));
544 FrameScope scope(
masm_.get(), StackFrame::MANUAL);
545 CallCFunctionFromIrregexpCode(
546 ExternalReference::re_is_character_in_range_array(), kNumArguments);
549 PopCallerSavedRegisters();
552bool RegExpMacroAssemblerIA32::CheckCharacterInRangeArray(
553 const ZoneList<CharacterRange>* ranges, Label* on_in_range) {
554 CallIsCharacterInRangeArray(ranges);
556 BranchOrBacktrack(not_zero, on_in_range);
560bool RegExpMacroAssemblerIA32::CheckCharacterNotInRangeArray(
561 const ZoneList<CharacterRange>* ranges, Label* on_not_in_range) {
562 CallIsCharacterInRangeArray(ranges);
564 BranchOrBacktrack(zero, on_not_in_range);
568void RegExpMacroAssemblerIA32::CheckBitInTable(
569 Handle<ByteArray> table,
571 __ mov(eax, Immediate(table));
572 Register index = current_character();
573 if (
mode_ != LATIN1 || kTableMask != String::kMaxOneByteCharCode) {
574 __ mov(ebx, kTableSize - 1);
575 __ and_(ebx, current_character());
580 BranchOrBacktrack(not_equal, on_bit_set);
583void RegExpMacroAssemblerIA32::SkipUntilBitInTable(
584 int cp_offset, Handle<ByteArray> table, Handle<ByteArray> nibble_table,
589 LoadCurrentCharacter(cp_offset, &cont,
true);
590 CheckBitInTable(table, &cont);
591 AdvanceCurrentPosition(advance_by);
596bool RegExpMacroAssemblerIA32::CheckSpecialClassRanges(
597 StandardCharacterSet type, Label* on_no_match) {
602 case StandardCharacterSet::kWhitespace:
604 if (
mode_ == LATIN1) {
607 __ cmp(current_character(),
' ');
608 __ j(equal, &success, Label::kNear);
610 __ lea(eax, Operand(current_character(), -
'\t'));
611 __ cmp(eax,
'\r' -
'\t');
612 __ j(below_equal, &success, Label::kNear);
614 __ cmp(eax, 0x00A0 -
'\t');
615 BranchOrBacktrack(not_equal, on_no_match);
620 case StandardCharacterSet::kNotWhitespace:
623 case StandardCharacterSet::kDigit:
625 __ lea(eax, Operand(current_character(), -
'0'));
626 __ cmp(eax,
'9' -
'0');
627 BranchOrBacktrack(above, on_no_match);
629 case StandardCharacterSet::kNotDigit:
631 __ lea(eax, Operand(current_character(), -
'0'));
632 __ cmp(eax,
'9' -
'0');
633 BranchOrBacktrack(below_equal, on_no_match);
635 case StandardCharacterSet::kLineTerminator:
638 __ mov(eax, current_character());
639 __ xor_(eax, Immediate(0x01));
641 __ sub(eax, Immediate(0x0B));
642 __ cmp(eax, 0x0C - 0x0B);
643 if (
mode_ == LATIN1) {
644 BranchOrBacktrack(above, on_no_match);
647 BranchOrBacktrack(below_equal, &done);
652 __ sub(eax, Immediate(0x2028 - 0x0B));
654 BranchOrBacktrack(above, on_no_match);
658 case StandardCharacterSet::kNotLineTerminator: {
660 __ mov(eax, current_character());
661 __ xor_(eax, Immediate(0x01));
663 __ sub(eax, Immediate(0x0B));
664 __ cmp(eax, 0x0C - 0x0B);
665 BranchOrBacktrack(below_equal, on_no_match);
670 __ sub(eax, Immediate(0x2028 - 0x0B));
671 __ cmp(eax, 0x2029 - 0x2028);
672 BranchOrBacktrack(below_equal, on_no_match);
676 case StandardCharacterSet::kWord: {
677 if (
mode_ != LATIN1) {
679 __ cmp(current_character(), Immediate(
'z'));
680 BranchOrBacktrack(above, on_no_match);
683 word_character_map[0]);
684 ExternalReference word_map = ExternalReference::re_word_character_map();
685 __ test_b(current_character(),
686 Operand(current_character(), times_1, word_map.address(),
687 RelocInfo::EXTERNAL_REFERENCE));
688 BranchOrBacktrack(zero, on_no_match);
691 case StandardCharacterSet::kNotWord: {
693 if (
mode_ != LATIN1) {
695 __ cmp(current_character(), Immediate(
'z'));
699 word_character_map[0]);
700 ExternalReference word_map = ExternalReference::re_word_character_map();
701 __ test_b(current_character(),
702 Operand(current_character(), times_1, word_map.address(),
703 RelocInfo::EXTERNAL_REFERENCE));
704 BranchOrBacktrack(not_zero, on_no_match);
705 if (
mode_ != LATIN1) {
711 case StandardCharacterSet::kEverything:
717void RegExpMacroAssemblerIA32::Fail() {
720 __ Move(eax, Immediate(FAILURE));
722 __ jmp(&exit_label_);
725void RegExpMacroAssemblerIA32::LoadRegExpStackPointerFromMemory(Register dst) {
726 ExternalReference ref =
727 ExternalReference::address_of_regexp_stack_stack_pointer(
isolate());
728 __ mov(dst,
__ ExternalReferenceAsOperand(ref, dst));
731void RegExpMacroAssemblerIA32::StoreRegExpStackPointerToMemory(
732 Register src, Register scratch) {
733 ExternalReference ref =
734 ExternalReference::address_of_regexp_stack_stack_pointer(
isolate());
735 __ mov(
__ ExternalReferenceAsOperand(ref, scratch), src);
738void RegExpMacroAssemblerIA32::PushRegExpBasePointer(Register stack_pointer,
740 ExternalReference ref =
741 ExternalReference::address_of_regexp_stack_memory_top_address(
isolate());
742 __ mov(scratch,
__ ExternalReferenceAsOperand(ref, scratch));
743 __ sub(scratch, stack_pointer);
744 __ mov(Operand(ebp, kRegExpStackBasePointerOffset), scratch);
747void RegExpMacroAssemblerIA32::PopRegExpBasePointer(Register stack_pointer_out,
749 ExternalReference ref =
750 ExternalReference::address_of_regexp_stack_memory_top_address(
isolate());
751 __ mov(scratch, Operand(ebp, kRegExpStackBasePointerOffset));
752 __ mov(stack_pointer_out,
753 __ ExternalReferenceAsOperand(ref, stack_pointer_out));
754 __ sub(stack_pointer_out, scratch);
755 StoreRegExpStackPointerToMemory(stack_pointer_out, scratch);
758DirectHandle<HeapObject> RegExpMacroAssemblerIA32::GetCode(
759 DirectHandle<String> source, RegExpFlags flags) {
765 __ bind(&entry_label_);
769 FrameScope scope(
masm_.get(), StackFrame::MANUAL);
774 __ EnterFrame(StackFrame::IRREGEXP);
781 static_assert(kLastCalleeSaveRegisterOffset == kBackupEbxOffset);
783 static_assert(kSuccessfulCapturesOffset ==
786 static_assert(kStringStartMinusOneOffset ==
789 static_assert(kBacktrackCountOffset ==
792 static_assert(kRegExpStackBasePointerOffset ==
798 static_assert(backtrack_stackpointer() == ecx);
799 LoadRegExpStackPointerFromMemory(backtrack_stackpointer());
803 PushRegExpBasePointer(backtrack_stackpointer(), eax);
807 Label stack_limit_hit, stack_ok;
809 ExternalReference stack_limit =
810 ExternalReference::address_of_jslimit(
isolate());
812 __ sub(eax, StaticVariable(stack_limit));
813 Immediate extra_space_for_variables(num_registers_ * kSystemPointerSize);
816 __ j(below_equal, &stack_limit_hit);
819 __ cmp(eax, extra_space_for_variables);
820 __ j(above_equal, &stack_ok);
823 __ mov(eax, EXCEPTION);
826 __ bind(&stack_limit_hit);
827 __ push(backtrack_stackpointer());
828 CallCheckStackGuardState(ebx, extra_space_for_variables);
829 __ pop(backtrack_stackpointer());
832 __ j(not_zero, &return_eax);
838 __ mov(ebx, Operand(ebp, kStartIndexOffset));
841 __ AllocateStackSpace(num_registers_ * kSystemPointerSize);
843 __ mov(esi, Operand(ebp, kInputEndOffset));
845 __ mov(edi, Operand(ebp, kInputStartOffset));
853 __ lea(eax, Operand(edi, ebx, times_2, -char_size()));
855 __ lea(eax, Operand(edi, ebx, times_1, -char_size()));
859 __ mov(Operand(ebp, kStringStartMinusOneOffset), eax);
861 Label load_char_start_regexp;
866 __ cmp(Operand(ebp, kStartIndexOffset), Immediate(0));
867 __ j(not_equal, &load_char_start_regexp, Label::kNear);
868 __ mov(current_character(),
'\n');
869 __ jmp(&start_regexp, Label::kNear);
872 __ bind(&load_char_start_regexp);
874 LoadCurrentCharacterUnchecked(-1, 1);
875 __ bind(&start_regexp);
879 if (num_saved_registers_ > 0) {
883 if (num_saved_registers_ > 8) {
884 DCHECK_EQ(ecx, backtrack_stackpointer());
886 __ mov(ecx, kRegisterZeroOffset);
889 __ mov(Operand(ebp, ecx, times_1, 0), eax);
890 __ sub(ecx, Immediate(kSystemPointerSize));
892 kRegisterZeroOffset - num_saved_registers_ * kSystemPointerSize);
893 __ j(greater, &init_loop);
896 for (
int i = 0;
i < num_saved_registers_;
i++) {
897 __ mov(register_location(
i), eax);
902 __ jmp(&start_label_);
905 if (success_label_.is_linked()) {
907 __ bind(&success_label_);
908 if (num_saved_registers_ > 0) {
910 __ mov(ebx, Operand(ebp, kRegisterOutputOffset));
911 __ mov(ecx, Operand(ebp, kInputEndOffset));
912 __ mov(edx, Operand(ebp, kStartIndexOffset));
913 __ sub(ecx, Operand(ebp, kInputStartOffset));
915 __ lea(ecx, Operand(ecx, edx, times_2, 0));
919 for (
int i = 0;
i < num_saved_registers_;
i++) {
920 __ mov(eax, register_location(
i));
921 if (
i == 0 && global_with_zero_length_check()) {
930 __ mov(Operand(ebx,
i * kSystemPointerSize), eax);
937 __ inc(Operand(ebp, kSuccessfulCapturesOffset));
940 __ mov(ecx, Operand(ebp, kNumOutputRegistersOffset));
941 __ sub(ecx, Immediate(num_saved_registers_));
943 __ cmp(ecx, Immediate(num_saved_registers_));
944 __ j(less, &exit_label_);
946 __ mov(Operand(ebp, kNumOutputRegistersOffset), ecx);
948 __ add(Operand(ebp, kRegisterOutputOffset),
949 Immediate(num_saved_registers_ * kSystemPointerSize));
953 PopRegExpBasePointer(backtrack_stackpointer(), ebx);
955 Label reload_string_start_minus_one;
957 if (global_with_zero_length_check()) {
962 __ j(not_equal, &reload_string_start_minus_one);
965 __ j(zero, &exit_label_, Label::kNear);
970 __ add(edi, Immediate(2));
974 if (global_unicode()) CheckNotInSurrogatePair(0, &advance);
977 __ bind(&reload_string_start_minus_one);
980 __ mov(eax, Operand(ebp, kStringStartMinusOneOffset));
982 __ jmp(&load_char_start_regexp);
984 __ mov(eax, Immediate(SUCCESS));
988 __ bind(&exit_label_);
991 __ mov(eax, Operand(ebp, kSuccessfulCapturesOffset));
994 __ bind(&return_eax);
997 PopRegExpBasePointer(backtrack_stackpointer(), ebx);
1000 __ lea(esp, Operand(ebp, kLastCalleeSaveRegisterOffset));
1002 static_assert(kNumCalleeSaveRegisters == 3);
1010 __ LeaveFrame(StackFrame::IRREGEXP);
1014 if (backtrack_label_.is_linked()) {
1015 __ bind(&backtrack_label_);
1019 Label exit_with_exception;
1022 if (check_preempt_label_.is_linked()) {
1023 SafeCallTarget(&check_preempt_label_);
1025 StoreRegExpStackPointerToMemory(backtrack_stackpointer(), edi);
1029 CallCheckStackGuardState(ebx);
1033 __ j(not_zero, &return_eax);
1037 LoadRegExpStackPointerFromMemory(backtrack_stackpointer());
1040 __ mov(esi, Operand(ebp, kInputEndOffset));
1045 if (stack_overflow_label_.is_linked()) {
1046 SafeCallTarget(&stack_overflow_label_);
1053 StoreRegExpStackPointerToMemory(backtrack_stackpointer(), edi);
1056 static const int kNumArguments = 1;
1057 __ PrepareCallCFunction(kNumArguments, ebx);
1058 __ mov(Operand(esp, 0 * kSystemPointerSize),
1059 Immediate(ExternalReference::isolate_address(
isolate())));
1060 CallCFunctionFromIrregexpCode(ExternalReference::re_grow_stack(),
1065 __ j(equal, &exit_with_exception);
1067 __ mov(backtrack_stackpointer(), eax);
1074 if (exit_with_exception.is_linked()) {
1076 __ bind(&exit_with_exception);
1078 __ mov(eax, EXCEPTION);
1079 __ jmp(&return_eax);
1082 if (fallback_label_.is_linked()) {
1083 __ bind(&fallback_label_);
1084 __ mov(eax, FALLBACK_TO_EXPERIMENTAL);
1085 __ jmp(&return_eax);
1092 .set_self_reference(
masm_->CodeObject())
1093 .set_empty_source_position_table()
1096 RegExpCodeCreateEvent(Cast<AbstractCode>(code), source, flags));
1097 return Cast<HeapObject>(code);
1100void RegExpMacroAssemblerIA32::GoTo(Label* to) { BranchOrBacktrack(to); }
1102void RegExpMacroAssemblerIA32::IfRegisterGE(
int reg,
1105 __ cmp(register_location(
reg), Immediate(comparand));
1106 BranchOrBacktrack(greater_equal, if_ge);
1110void RegExpMacroAssemblerIA32::IfRegisterLT(
int reg,
1113 __ cmp(register_location(
reg), Immediate(comparand));
1114 BranchOrBacktrack(less, if_lt);
1118void RegExpMacroAssemblerIA32::IfRegisterEqPos(
int reg,
1120 __ cmp(edi, register_location(
reg));
1121 BranchOrBacktrack(equal, if_eq);
1125RegExpMacroAssembler::IrregexpImplementation
1126 RegExpMacroAssemblerIA32::Implementation() {
1127 return kIA32Implementation;
1131void RegExpMacroAssemblerIA32::PopCurrentPosition() {
1136void RegExpMacroAssemblerIA32::PopRegister(
int register_index) {
1138 __ mov(register_location(register_index), eax);
1142void RegExpMacroAssemblerIA32::PushBacktrack(Label*
label) {
1143 Push(Immediate::CodeRelativeOffset(
label));
1148void RegExpMacroAssemblerIA32::PushCurrentPosition() {
1154void RegExpMacroAssemblerIA32::PushRegister(
int register_index,
1155 StackCheckFlag check_stack_limit) {
1156 __ mov(eax, register_location(register_index));
1158 if (check_stack_limit) {
1161 AssertAboveStackLimitMinusSlack();
1166void RegExpMacroAssemblerIA32::ReadCurrentPositionFromRegister(
int reg) {
1167 __ mov(edi, register_location(
reg));
1170void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(
int reg) {
1171 ExternalReference stack_top_address =
1172 ExternalReference::address_of_regexp_stack_memory_top_address(
isolate());
1173 __ mov(eax,
__ ExternalReferenceAsOperand(stack_top_address, eax));
1174 __ sub(eax, backtrack_stackpointer());
1175 __ mov(register_location(
reg), eax);
1178void RegExpMacroAssemblerIA32::ReadStackPointerFromRegister(
int reg) {
1179 ExternalReference stack_top_address =
1180 ExternalReference::address_of_regexp_stack_memory_top_address(
isolate());
1181 __ mov(backtrack_stackpointer(),
1182 __ ExternalReferenceAsOperand(stack_top_address,
1183 backtrack_stackpointer()));
1184 __ sub(backtrack_stackpointer(), register_location(
reg));
1187void RegExpMacroAssemblerIA32::SetCurrentPositionFromEnd(
int by) {
1188 Label after_position;
1189 __ cmp(edi, -by * char_size());
1190 __ j(greater_equal, &after_position, Label::kNear);
1191 __ mov(edi, -by * char_size());
1195 LoadCurrentCharacterUnchecked(-1, 1);
1196 __ bind(&after_position);
1200void RegExpMacroAssemblerIA32::SetRegister(
int register_index,
int to) {
1201 DCHECK(register_index >= num_saved_registers_);
1202 __ mov(register_location(register_index), Immediate(to));
1206bool RegExpMacroAssemblerIA32::Succeed() {
1207 __ jmp(&success_label_);
1212void RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister(
int reg,
1214 if (cp_offset == 0) {
1215 __ mov(register_location(
reg), edi);
1217 __ lea(eax, Operand(edi, cp_offset * char_size()));
1218 __ mov(register_location(
reg), eax);
1223void RegExpMacroAssemblerIA32::ClearRegisters(
int reg_from,
int reg_to) {
1224 DCHECK(reg_from <= reg_to);
1225 __ mov(eax, Operand(ebp, kStringStartMinusOneOffset));
1226 for (
int reg = reg_from;
reg <= reg_to;
reg++) {
1227 __ mov(register_location(
reg), eax);
1233void RegExpMacroAssemblerIA32::CallCheckStackGuardState(Register scratch,
1234 Immediate extra_space) {
1235 static const int num_arguments = 4;
1236 __ PrepareCallCFunction(num_arguments, scratch);
1238 __ mov(Operand(esp, 3 * kSystemPointerSize), extra_space);
1240 __ mov(Operand(esp, 2 * kSystemPointerSize), ebp);
1242 __ mov(Operand(esp, 1 * kSystemPointerSize), Immediate(
masm_->CodeObject()));
1244 __ lea(eax, Operand(esp, -kSystemPointerSize));
1245 __ mov(Operand(esp, 0 * kSystemPointerSize), eax);
1246 ExternalReference check_stack_guard =
1247 ExternalReference::re_check_stack_guard_state();
1248 CallCFunctionFromIrregexpCode(check_stack_guard, num_arguments);
1251Operand RegExpMacroAssemblerIA32::StaticVariable(
const ExternalReference& ext) {
1252 return Operand(ext.address(), RelocInfo::EXTERNAL_REFERENCE);
1256template <
typename T>
1257static T& frame_entry(Address re_frame,
int frame_offset) {
1258 return reinterpret_cast<T&
>(Memory<int32_t>(re_frame + frame_offset));
1262template <
typename T>
1263static T* frame_entry_address(Address re_frame,
int frame_offset) {
1264 return reinterpret_cast<T*
>(re_frame + frame_offset);
1267int RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address,
1270 uintptr_t extra_space) {
1271 Tagged<InstructionStream> re_code =
1272 Cast<InstructionStream>(Tagged<Object>(raw_code));
1273 return NativeRegExpMacroAssembler::CheckStackGuardState(
1274 frame_entry<Isolate*>(re_frame, kIsolateOffset),
1275 frame_entry<int>(re_frame, kStartIndexOffset),
1276 static_cast<RegExp::CallOrigin
>(
1277 frame_entry<int>(re_frame, kDirectCallOffset)),
1278 return_address, re_code,
1279 frame_entry_address<Address>(re_frame, kInputStringOffset),
1280 frame_entry_address<const uint8_t*>(re_frame, kInputStartOffset),
1281 frame_entry_address<const uint8_t*>(re_frame, kInputEndOffset),
1285Operand RegExpMacroAssemblerIA32::register_location(
int register_index) {
1286 DCHECK(register_index < (1<<30));
1287 if (num_registers_ <= register_index) {
1288 num_registers_ = register_index + 1;
1291 kRegisterZeroOffset - register_index * kSystemPointerSize);
1295void RegExpMacroAssemblerIA32::CheckPosition(
int cp_offset,
1296 Label* on_outside_input) {
1297 if (cp_offset >= 0) {
1298 __ cmp(edi, -cp_offset * char_size());
1299 BranchOrBacktrack(greater_equal, on_outside_input);
1301 __ lea(eax, Operand(edi, cp_offset * char_size()));
1302 __ cmp(eax, Operand(ebp, kStringStartMinusOneOffset));
1303 BranchOrBacktrack(less_equal, on_outside_input);
1307void RegExpMacroAssemblerIA32::BranchOrBacktrack(Label* to) {
1308 if (to ==
nullptr) {
1315void RegExpMacroAssemblerIA32::BranchOrBacktrack(Condition
condition,
1320void RegExpMacroAssemblerIA32::SafeCall(Label* to) {
1322 __ push(Immediate::CodeRelativeOffset(&return_to));
1324 __ bind(&return_to);
1328void RegExpMacroAssemblerIA32::SafeReturn() {
1330 __ add(ebx, Immediate(
masm_->CodeObject()));
1335void RegExpMacroAssemblerIA32::SafeCallTarget(Label* name) {
1340void RegExpMacroAssemblerIA32::Push(Register source) {
1341 DCHECK(source != backtrack_stackpointer());
1343 __ sub(backtrack_stackpointer(), Immediate(kSystemPointerSize));
1344 __ mov(Operand(backtrack_stackpointer(), 0), source);
1348void RegExpMacroAssemblerIA32::Push(Immediate value) {
1350 __ sub(backtrack_stackpointer(), Immediate(kSystemPointerSize));
1351 __ mov(Operand(backtrack_stackpointer(), 0), value);
1355void RegExpMacroAssemblerIA32::Pop(Register target) {
1356 DCHECK(target != backtrack_stackpointer());
1357 __ mov(target, Operand(backtrack_stackpointer(), 0));
1359 __ add(backtrack_stackpointer(), Immediate(kSystemPointerSize));
1363void RegExpMacroAssemblerIA32::CheckPreemption() {
1366 ExternalReference stack_limit =
1367 ExternalReference::address_of_jslimit(
isolate());
1368 __ cmp(esp, StaticVariable(stack_limit));
1369 __ j(above, &no_preempt);
1371 SafeCall(&check_preempt_label_);
1373 __ bind(&no_preempt);
1377void RegExpMacroAssemblerIA32::CheckStackLimit() {
1378 Label no_stack_overflow;
1379 ExternalReference stack_limit =
1380 ExternalReference::address_of_regexp_stack_limit_address(
isolate());
1381 __ cmp(backtrack_stackpointer(), StaticVariable(stack_limit));
1382 __ j(above, &no_stack_overflow);
1384 SafeCall(&stack_overflow_label_);
1386 __ bind(&no_stack_overflow);
1389void RegExpMacroAssemblerIA32::AssertAboveStackLimitMinusSlack() {
1391 Label no_stack_overflow;
1393 auto l = ExternalReference::address_of_regexp_stack_limit_address(
isolate());
1394 __ mov(eax,
__ ExternalReferenceAsOperand(l, eax));
1395 __ sub(eax, Immediate(RegExpStack::kStackLimitSlackSize));
1396 __ cmp(backtrack_stackpointer(), eax);
1397 __ j(above, &no_stack_overflow);
1399 __ bind(&no_stack_overflow);
1402void RegExpMacroAssemblerIA32::LoadCurrentCharacterUnchecked(
int cp_offset,
1404 if (
mode_ == LATIN1) {
1405 if (characters == 4) {
1406 __ mov(current_character(), Operand(esi, edi, times_1, cp_offset));
1407 }
else if (characters == 2) {
1408 __ movzx_w(current_character(), Operand(esi, edi, times_1, cp_offset));
1411 __ movzx_b(current_character(), Operand(esi, edi, times_1, cp_offset));
1415 if (characters == 2) {
1416 __ mov(current_character(),
1417 Operand(esi, edi, times_1, cp_offset *
sizeof(base::uc16)));
1420 __ movzx_w(current_character(),
1421 Operand(esi, edi, times_1, cp_offset *
sizeof(base::uc16)));
static constexpr int kRegExpCodeSize
RegExpMacroAssemblerIA32(Isolate *isolate, Zone *zone, Mode mode, int registers_to_save)
#define PROFILE(the_isolate, Call)
RecordWriteMode const mode_
const CodeDesc * code_desc
#define ASM_CODE_COMMENT_STRING(asm,...)
MaglevAssembler *const masm_
void push(LiftoffAssembler *assm, LiftoffRegister reg, ValueKind kind, int padding=0)
Operand FieldOperand(Register object, int offset)
constexpr int kSystemPointerSize
std::unique_ptr< AssemblerBuffer > NewAssemblerBuffer(int size)
V8_EXPORT_PRIVATE FlagValues v8_flags
#define DCHECK_LE(v1, v2)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
#define DCHECK_GT(v1, v2)
#define OFFSET_OF_DATA_START(Type)
#define V8_UNLIKELY(condition)