Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(181)

Side by Side Diff: src/regexp-macro-assembler-ia32.cc

Issue 13783: * Made preemption work in Irregexp-native-ia32 (Closed)
Patch Set: Addressed review comments Created 12 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/regexp-macro-assembler-ia32.h ('k') | src/runtime.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2008 the V8 project authors. All rights reserved. 1 // Copyright 2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 } 100 }
101 101
102 102
103 RegExpMacroAssemblerIA32::~RegExpMacroAssemblerIA32() { 103 RegExpMacroAssemblerIA32::~RegExpMacroAssemblerIA32() {
104 delete masm_; 104 delete masm_;
105 // Unuse labels in case we throw away the assembler without calling GetCode. 105 // Unuse labels in case we throw away the assembler without calling GetCode.
106 entry_label_.Unuse(); 106 entry_label_.Unuse();
107 start_label_.Unuse(); 107 start_label_.Unuse();
108 success_label_.Unuse(); 108 success_label_.Unuse();
109 exit_label_.Unuse(); 109 exit_label_.Unuse();
110 check_preempt_label_.Unuse();
110 } 111 }
111 112
112 113
113 void RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) { 114 void RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) {
114 if (by != 0) { 115 if (by != 0) {
115 Label inside_string; 116 Label inside_string;
116 __ add(Operand(edi), Immediate(by * char_size())); 117 __ add(Operand(edi), Immediate(by * char_size()));
117 } 118 }
118 } 119 }
119 120
120 121
121 void RegExpMacroAssemblerIA32::AdvanceRegister(int reg, int by) { 122 void RegExpMacroAssemblerIA32::AdvanceRegister(int reg, int by) {
122 ASSERT(reg >= 0); 123 ASSERT(reg >= 0);
123 ASSERT(reg < num_registers_); 124 ASSERT(reg < num_registers_);
124 __ add(register_location(reg), Immediate(by)); 125 __ add(register_location(reg), Immediate(by));
125 } 126 }
126 127
127 128
128 void RegExpMacroAssemblerIA32::Backtrack() { 129 void RegExpMacroAssemblerIA32::Backtrack() {
129 __ pop(ecx); 130 SafeReturn();
130 __ add(Operand(ecx), Immediate(self_));
131 __ jmp(Operand(ecx));
132 } 131 }
133 132
134 133
135 void RegExpMacroAssemblerIA32::Bind(Label* label) { 134 void RegExpMacroAssemblerIA32::Bind(Label* label) {
136 __ bind(label); 135 __ bind(label);
137 } 136 }
138 137
139 void RegExpMacroAssemblerIA32::CheckBitmap(uc16 start, 138 void RegExpMacroAssemblerIA32::CheckBitmap(uc16 start,
140 Label* bitmap, 139 Label* bitmap,
141 Label* on_zero) { 140 Label* on_zero) {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 } 207 }
209 return; 208 return;
210 } 209 }
211 210
212 ArraySlice constant_buffer = constants_.GetBuffer(str.length(), char_size()); 211 ArraySlice constant_buffer = constants_.GetBuffer(str.length(), char_size());
213 if (mode_ == ASCII) { 212 if (mode_ == ASCII) {
214 for (int i = 0; i < str.length(); i++) { 213 for (int i = 0; i < str.length(); i++) {
215 constant_buffer.at<char>(i) = static_cast<char>(str[i]); 214 constant_buffer.at<char>(i) = static_cast<char>(str[i]);
216 } 215 }
217 } else { 216 } else {
217 ASSERT(mode_ == UC16);
218 memcpy(constant_buffer.location(), 218 memcpy(constant_buffer.location(),
219 str.start(), 219 str.start(),
220 str.length() * sizeof(uc16)); 220 str.length() * sizeof(uc16));
221 } 221 }
222 222
223 __ mov(eax, edi); 223 __ mov(eax, edi);
224 __ mov(ebx, esi); 224 __ mov(ebx, esi);
225 __ lea(edi, Operand(esi, edi, times_1, byte_offset)); 225 __ lea(edi, Operand(esi, edi, times_1, byte_offset));
226 LoadConstantBufferAddress(esi, &constant_buffer); 226 LoadConstantBufferAddress(esi, &constant_buffer);
227 __ mov(ecx, str.length()); 227 __ mov(ecx, str.length());
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 __ bind(&fail); 285 __ bind(&fail);
286 __ pop(edi); 286 __ pop(edi);
287 __ pop(esi); 287 __ pop(esi);
288 BranchOrBacktrack(no_condition, on_no_match); 288 BranchOrBacktrack(no_condition, on_no_match);
289 289
290 __ bind(&success); 290 __ bind(&success);
291 __ pop(eax); // discard original value of edi 291 __ pop(eax); // discard original value of edi
292 __ pop(esi); 292 __ pop(esi);
293 __ sub(edi, Operand(esi)); 293 __ sub(edi, Operand(esi));
294 } else { 294 } else {
295 // store state 295 ASSERT(mode_ == UC16);
296 __ push(esi); 296 __ push(esi);
297 __ push(edi); 297 __ push(edi);
298 __ push(ecx); 298 __ push(ecx);
299 // align stack 299 const int four_arguments = 4;
300 int frameAlignment = OS::ActivationFrameAlignment(); 300 FrameAlign(four_arguments);
301 if (frameAlignment != 0) {
302 __ mov(ebx, esp);
303 __ sub(Operand(esp), Immediate(5 * kPointerSize)); // args + esp.
304 ASSERT(IsPowerOf2(frameAlignment));
305 __ and_(esp, -frameAlignment);
306 __ mov(Operand(esp, 4 * kPointerSize), ebx);
307 } else {
308 __ sub(Operand(esp), Immediate(4 * kPointerSize));
309 }
310 // Put arguments on stack. 301 // Put arguments on stack.
311 __ mov(Operand(esp, 3 * kPointerSize), ecx); 302 __ mov(Operand(esp, 3 * kPointerSize), ecx);
312 __ mov(ebx, Operand(ebp, kInputEndOffset)); 303 __ mov(ebx, Operand(ebp, kInputEndOffset));
313 __ add(edi, Operand(ebx)); 304 __ add(edi, Operand(ebx));
314 __ mov(Operand(esp, 2 * kPointerSize), edi); 305 __ mov(Operand(esp, 2 * kPointerSize), edi);
315 __ add(eax, Operand(ebx)); 306 __ add(eax, Operand(ebx));
316 __ mov(Operand(esp, 1 * kPointerSize), eax); 307 __ mov(Operand(esp, 1 * kPointerSize), eax);
317 __ mov(eax, Operand(ebp, kInputBuffer)); 308 __ mov(eax, Operand(ebp, kInputBuffer));
318 __ mov(Operand(esp, 0 * kPointerSize), eax); 309 __ mov(Operand(esp, 0 * kPointerSize), eax);
319 Address function_address = FUNCTION_ADDR(&CaseInsensitiveCompareUC16); 310 Address function_address = FUNCTION_ADDR(&CaseInsensitiveCompareUC16);
320 __ mov(Operand(eax), 311 CallCFunction(function_address, four_arguments);
321 Immediate(reinterpret_cast<int32_t>(function_address)));
322 __ call(Operand(eax));
323 if (frameAlignment != 0) {
324 __ mov(esp, Operand(esp, 4 * kPointerSize));
325 } else {
326 __ add(Operand(esp), Immediate(4 * sizeof(int32_t)));
327 }
328 __ pop(ecx); 312 __ pop(ecx);
329 __ pop(edi); 313 __ pop(edi);
330 __ pop(esi); 314 __ pop(esi);
315
331 __ or_(eax, Operand(eax)); 316 __ or_(eax, Operand(eax));
332 BranchOrBacktrack(zero, on_no_match); 317 BranchOrBacktrack(zero, on_no_match);
333 __ add(edi, Operand(ecx)); 318 __ add(edi, Operand(ecx));
334 } 319 }
335 __ bind(&fallthrough); 320 __ bind(&fallthrough);
336 } 321 }
337 322
338 323
339 void RegExpMacroAssemblerIA32::CheckNotBackReference( 324 void RegExpMacroAssemblerIA32::CheckNotBackReference(
340 int start_reg, 325 int start_reg,
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 __ cmp(Operand(ebp, kAtStart), Immediate(0)); 514 __ cmp(Operand(ebp, kAtStart), Immediate(0));
530 __ j(not_equal, &at_start); 515 __ j(not_equal, &at_start);
531 LoadCurrentCharacterUnchecked(-1); // Load previous char. 516 LoadCurrentCharacterUnchecked(-1); // Load previous char.
532 __ jmp(&start_label_); 517 __ jmp(&start_label_);
533 __ bind(&at_start); 518 __ bind(&at_start);
534 __ mov(current_character(), '\n'); 519 __ mov(current_character(), '\n');
535 __ jmp(&start_label_); 520 __ jmp(&start_label_);
536 521
537 522
538 // Exit code: 523 // Exit code:
539 // Success 524 if (success_label_.is_linked()) {
540 __ bind(&success_label_); 525 // Success
541 if (num_saved_registers_ > 0) { 526 __ bind(&success_label_);
542 // copy captures to output 527 if (num_saved_registers_ > 0) {
543 __ mov(ebx, Operand(ebp, kRegisterOutput)); 528 // copy captures to output
544 __ mov(ecx, Operand(ebp, kInputEndOffset)); 529 __ mov(ebx, Operand(ebp, kRegisterOutput));
545 __ sub(ecx, Operand(ebp, kInputStartOffset)); 530 __ mov(ecx, Operand(ebp, kInputEndOffset));
546 for (int i = 0; i < num_saved_registers_; i++) { 531 __ sub(ecx, Operand(ebp, kInputStartOffset));
547 __ mov(eax, register_location(i)); 532 for (int i = 0; i < num_saved_registers_; i++) {
548 __ add(eax, Operand(ecx)); // Convert to index from start, not end. 533 __ mov(eax, register_location(i));
549 if (char_size() > 1) { 534 __ add(eax, Operand(ecx)); // Convert to index from start, not end.
550 ASSERT(char_size() == 2); 535 if (mode_ == UC16) {
551 __ sar(eax, 1); // Convert to character index, not byte. 536 __ sar(eax, 1); // Convert byte index to character index.
537 }
538 __ mov(Operand(ebx, i * kPointerSize), eax);
552 } 539 }
553 __ mov(Operand(ebx, i * kPointerSize), eax);
554 } 540 }
541 __ mov(eax, Immediate(1));
555 } 542 }
556 __ mov(eax, Immediate(1));
557
558 // Exit and return eax 543 // Exit and return eax
559 __ bind(&exit_label_); 544 __ bind(&exit_label_);
560 __ leave(); 545 __ leave();
561 __ pop(ebx); 546 __ pop(ebx);
562 __ pop(edi); 547 __ pop(edi);
563 __ pop(esi); 548 __ pop(esi);
564 __ ret(0); 549 __ ret(0);
565 550
551 // Preempt-code
552 if (check_preempt_label_.is_linked()) {
553 __ bind(&check_preempt_label_);
554 // TODO(lrn): call C function to check the stack guard and return current
555 // stack state (0 = ok, positive = out of stack, negative = preempt).
556 // Then dispatch to an action depending on state, and loop.
557 __ push(edi);
558
559 Label retry;
560 Label stack_overflow;
561
562 __ bind(&retry);
563 int num_arguments = 2;
564 FrameAlign(num_arguments);
565 __ mov(Operand(esp, 1 * kPointerSize), Immediate(self_));
566 __ lea(eax, Operand(esp, -kPointerSize));
567 __ mov(Operand(esp, 0 * kPointerSize), eax);
568 CallCFunction(FUNCTION_ADDR(&CheckStackGuardState), num_arguments);
569
570 ExternalReference stack_guard_limit =
571 ExternalReference::address_of_stack_guard_limit();
572
573 __ or_(eax, Operand(eax));
574 __ j(not_equal, &stack_overflow);
575
576 __ cmp(esp, Operand::StaticVariable(stack_guard_limit));
577 __ j(below_equal, &retry);
578
579 __ pop(edi);
580 // String might have moved: Recompute esi from scratch.
581 __ mov(esi, Operand(esp, kInputBuffer));
582 __ mov(esi, Operand(esi, 0));
583 __ add(esi, Operand(esp, kInputEndOffset));
584 SafeReturn();
585
586 __ bind(&stack_overflow);
587 // Exit with result -1 to signal thrown exception.
588 __ mov(eax, -1);
589 __ jmp(&exit_label_);
590 }
591
566 CodeDesc code_desc; 592 CodeDesc code_desc;
567 masm_->GetCode(&code_desc); 593 masm_->GetCode(&code_desc);
568 Handle<Code> code = Factory::NewCode(code_desc, 594 Handle<Code> code = Factory::NewCode(code_desc,
569 NULL, 595 NULL,
570 Code::ComputeFlags(Code::REGEXP), 596 Code::ComputeFlags(Code::REGEXP),
571 self_); 597 self_);
572 LOG(CodeCreateEvent("RegExp", *code, *(source->ToCString()))); 598 LOG(CodeCreateEvent("RegExp", *code, *(source->ToCString())));
573 return Handle<Object>::cast(code); 599 return Handle<Object>::cast(code);
574 } 600 }
575 601
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 __ pop(edi); 641 __ pop(edi);
616 } 642 }
617 643
618 644
619 void RegExpMacroAssemblerIA32::PopRegister(int register_index) { 645 void RegExpMacroAssemblerIA32::PopRegister(int register_index) {
620 __ pop(register_location(register_index)); 646 __ pop(register_location(register_index));
621 } 647 }
622 648
623 649
624 void RegExpMacroAssemblerIA32::PushBacktrack(Label* label) { 650 void RegExpMacroAssemblerIA32::PushBacktrack(Label* label) {
625 // CheckStackLimit(); // Not ready yet. 651 __ push(Immediate::CodeRelativeOffset(label));
626 __ push(label, RelocInfo::NONE); 652 CheckStackLimit();
627 } 653 }
628 654
629 655
630 void RegExpMacroAssemblerIA32::PushCurrentPosition() { 656 void RegExpMacroAssemblerIA32::PushCurrentPosition() {
631 __ push(edi); 657 __ push(edi);
632 } 658 }
633 659
634 660
635 void RegExpMacroAssemblerIA32::PushRegister(int register_index) { 661 void RegExpMacroAssemblerIA32::PushRegister(int register_index) {
636 __ push(register_location(register_index)); 662 __ push(register_location(register_index));
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
703 if (c1 != c2) { 729 if (c1 != c2) {
704 return 0; 730 return 0;
705 } 731 }
706 } 732 }
707 } 733 }
708 } 734 }
709 return 1; 735 return 1;
710 } 736 }
711 737
712 738
739 int RegExpMacroAssemblerIA32::CheckStackGuardState(Address return_address,
740 Code* re_code) {
741 if (StackGuard::IsStackOverflow()) {
742 Top::StackOverflow();
743 return 1;
744 }
745
746 // If not real stack overflow the stack guard was used to interrupt
747 // execution for another purpose.
748
749 // Prepare for possible GC.
750 Handle<Code> code_handle(re_code);
751 #ifdef DEBUG
752 CHECK(re_code->instruction_start() <= return_address);
753 CHECK(return_address <=
754 re_code->instruction_start() + re_code->instruction_size());
755 #endif
756
757 Object* result = Execution::HandleStackGuardInterrupt();
758
759 if (*code_handle != re_code) { // Return address no longer valid
760 int delta = *code_handle - re_code;
761 *reinterpret_cast<int32_t*>(return_address) += delta;
762 }
763
764 if (result->IsException()) {
765 return 1;
766 }
767 return 0;
768 }
769
770
713 Operand RegExpMacroAssemblerIA32::register_location(int register_index) { 771 Operand RegExpMacroAssemblerIA32::register_location(int register_index) {
714 ASSERT(register_index < (1<<30)); 772 ASSERT(register_index < (1<<30));
715 if (num_registers_ <= register_index) { 773 if (num_registers_ <= register_index) {
716 num_registers_ = register_index + 1; 774 num_registers_ = register_index + 1;
717 } 775 }
718 return Operand(ebp, -(register_index + 1) * kPointerSize); 776 return Operand(ebp, -(register_index + 1) * kPointerSize);
719 } 777 }
720 778
721 779
722 Register RegExpMacroAssemblerIA32::current_character() { 780 Register RegExpMacroAssemblerIA32::current_character() {
(...skipping 20 matching lines...) Expand all
743 Label skip; 801 Label skip;
744 __ j(NegateCondition(condition), &skip); 802 __ j(NegateCondition(condition), &skip);
745 Backtrack(); 803 Backtrack();
746 __ bind(&skip); 804 __ bind(&skip);
747 return; 805 return;
748 } 806 }
749 __ j(condition, to); 807 __ j(condition, to);
750 } 808 }
751 809
752 810
811 void RegExpMacroAssemblerIA32::SafeCall(Label* to) {
812 Label return_to;
813 __ push(Immediate::CodeRelativeOffset(&return_to));
814 __ jmp(to);
815 __ bind(&return_to);
816 }
817
818
819 void RegExpMacroAssemblerIA32::SafeReturn() {
820 __ pop(ecx);
821 __ add(Operand(ecx), Immediate(self_));
822 __ jmp(Operand(ecx));
823 }
824
825
753 void RegExpMacroAssemblerIA32::CheckStackLimit() { 826 void RegExpMacroAssemblerIA32::CheckStackLimit() {
754 if (FLAG_check_stack) { 827 if (FLAG_check_stack) {
755 // Check for preemption first. 828 // Check for preemption first.
756 Label no_preempt; 829 Label no_preempt;
757 Label retry_preempt;
758 // Check for preemption. 830 // Check for preemption.
759 ExternalReference stack_guard_limit = 831 ExternalReference stack_guard_limit =
760 ExternalReference::address_of_stack_guard_limit(); 832 ExternalReference::address_of_stack_guard_limit();
761 __ cmp(esp, Operand::StaticVariable(stack_guard_limit)); 833 __ cmp(esp, Operand::StaticVariable(stack_guard_limit));
762 __ j(above, &no_preempt, taken); 834 __ j(above, &no_preempt, taken);
763 __ push(edi); // Current position.
764 __ push(edx); // Current character.
765 // Restore original edi, esi.
766 __ mov(edi, Operand(ebp, kBackup_edi));
767 __ mov(esi, Operand(ebp, kBackup_esi));
768 835
769 __ bind(&retry_preempt); 836 SafeCall(&check_preempt_label_);
770 // simulate stack for Runtime call.
771 __ push(eax);
772 __ push(Immediate(Smi::FromInt(0))); // Dummy receiver
773 __ CallRuntime(Runtime::kStackGuard, 1);
774 __ pop(eax);
775
776 __ cmp(esp, Operand::StaticVariable(stack_guard_limit));
777 __ j(below_equal, &retry_preempt);
778
779 __ pop(edx);
780 __ pop(edi);
781 __ mov(esi, Operand(ebp, kInputBuffer));
782 __ mov(esi, Operand(esi, 0));
783 __ add(esi, Operand(ebp, kInputEndOffset));
784 837
785 __ bind(&no_preempt); 838 __ bind(&no_preempt);
786 } 839 }
787 } 840 }
788 841
789 842
843 void RegExpMacroAssemblerIA32::FrameAlign(int num_arguments) {
844 int frameAlignment = OS::ActivationFrameAlignment();
845 if (frameAlignment != 0) {
846 // Make stack end at alignment and make room for num_arguments words
847 // and the original value of esp.
848 __ mov(ebx, esp);
849 __ sub(Operand(esp), Immediate((num_arguments + 1) * kPointerSize));
850 ASSERT(IsPowerOf2(frameAlignment));
851 __ and_(esp, -frameAlignment);
852 __ mov(Operand(esp, num_arguments * kPointerSize), ebx);
853 } else {
854 __ sub(Operand(esp), Immediate(num_arguments * kPointerSize));
855 }
856 }
857
858
859 void RegExpMacroAssemblerIA32::CallCFunction(Address function_address,
860 int num_arguments) {
861 __ mov(Operand(eax), Immediate(reinterpret_cast<int32_t>(function_address)));
862 __ call(Operand(eax));
863 if (OS::ActivationFrameAlignment() != 0) {
864 __ mov(esp, Operand(esp, num_arguments * kPointerSize));
865 } else {
866 __ add(Operand(esp), Immediate(num_arguments * sizeof(int32_t)));
867 }
868 }
869
870
790 void RegExpMacroAssemblerIA32::LoadCurrentCharacterUnchecked(int cp_offset) { 871 void RegExpMacroAssemblerIA32::LoadCurrentCharacterUnchecked(int cp_offset) {
791 if (mode_ == ASCII) { 872 if (mode_ == ASCII) {
792 __ movzx_b(current_character(), Operand(esi, edi, times_1, cp_offset)); 873 __ movzx_b(current_character(), Operand(esi, edi, times_1, cp_offset));
793 return; 874 } else {
875 ASSERT(mode_ == UC16);
876 __ movzx_w(current_character(),
877 Operand(esi, edi, times_1, cp_offset * sizeof(uc16)));
794 } 878 }
795 ASSERT(mode_ == UC16);
796 __ movzx_w(current_character(),
797 Operand(esi, edi, times_1, cp_offset * sizeof(uc16)));
798 } 879 }
799 880
800 881
801 void RegExpMacroAssemblerIA32::LoadConstantBufferAddress(Register reg, 882 void RegExpMacroAssemblerIA32::LoadConstantBufferAddress(Register reg,
802 ArraySlice* buffer) { 883 ArraySlice* buffer) {
803 __ mov(reg, buffer->array()); 884 __ mov(reg, buffer->array());
804 __ add(Operand(reg), Immediate(buffer->base_offset())); 885 __ add(Operand(reg), Immediate(buffer->base_offset()));
805 } 886 }
806 887
807 #undef __ 888 #undef __
808 }} // namespace v8::internal 889 }} // namespace v8::internal
OLDNEW
« no previous file with comments | « src/regexp-macro-assembler-ia32.h ('k') | src/runtime.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698