| OLD | NEW |
| 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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 * The stack will have the following structure: | 56 * The stack will have the following structure: |
| 57 * - stack_area_top (High end of the memory area to use as | 57 * - stack_area_top (High end of the memory area to use as |
| 58 * backtracking stack) | 58 * backtracking stack) |
| 59 * - at_start (if 1, start at start of string, if 0, don't) | 59 * - at_start (if 1, start at start of string, if 0, don't) |
| 60 * - int* capture_array (int[num_saved_registers_], for output). | 60 * - int* capture_array (int[num_saved_registers_], for output). |
| 61 * - end of input (index of end of string, relative to *string_base) | 61 * - end of input (index of end of string, relative to *string_base) |
| 62 * - start of input (index of first character in string, relative | 62 * - start of input (index of first character in string, relative |
| 63 * to *string_base) | 63 * to *string_base) |
| 64 * - void** string_base (location of a handle containing the string) | 64 * - void** string_base (location of a handle containing the string) |
| 65 * - return address | 65 * - return address |
| 66 * ebp-> - old ebp |
| 66 * - backup of caller esi | 67 * - backup of caller esi |
| 67 * - backup of caller edi | 68 * - backup of caller edi |
| 68 * - backup of caller ebx | 69 * - backup of caller ebx |
| 69 * ebp-> - old ebp | |
| 70 * - register 0 ebp[-4] (Only positions must be stored in the first | 70 * - register 0 ebp[-4] (Only positions must be stored in the first |
| 71 * - register 1 ebp[-8] num_saved_registers_ registers) | 71 * - register 1 ebp[-8] num_saved_registers_ registers) |
| 72 * - ... | 72 * - ... |
| 73 * | 73 * |
| 74 * The first num_saved_registers_ registers are initialized to point to | 74 * The first num_saved_registers_ registers are initialized to point to |
| 75 * "character -1" in the string (i.e., char_size() bytes before the first | 75 * "character -1" in the string (i.e., char_size() bytes before the first |
| 76 * character of the string). The remaining registers starts out as garbage. | 76 * character of the string). The remaining registers starts out as garbage. |
| 77 * | 77 * |
| 78 * The data up to the return address must be placed there by the calling | 78 * The data up to the return address must be placed there by the calling |
| 79 * code, e.g., by calling the code as cast to: | 79 * code, e.g., by calling the code as cast to: |
| (...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 __ jmp(&exit_label_); | 593 __ jmp(&exit_label_); |
| 594 } | 594 } |
| 595 | 595 |
| 596 | 596 |
| 597 Handle<Object> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) { | 597 Handle<Object> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) { |
| 598 // Finalize code - write the entry point code now we know how many | 598 // Finalize code - write the entry point code now we know how many |
| 599 // registers we need. | 599 // registers we need. |
| 600 | 600 |
| 601 // Entry code: | 601 // Entry code: |
| 602 __ bind(&entry_label_); | 602 __ bind(&entry_label_); |
| 603 // Start new stack frame. |
| 604 __ push(ebp); |
| 605 __ mov(ebp, esp); |
| 603 // Save callee-save registers. Order here should correspond to order of | 606 // Save callee-save registers. Order here should correspond to order of |
| 604 // kBackup_ebx etc. | 607 // kBackup_ebx etc. |
| 605 __ push(esi); | 608 __ push(esi); |
| 606 __ push(edi); | 609 __ push(edi); |
| 607 __ push(ebx); // Callee-save on MacOS. | 610 __ push(ebx); // Callee-save on MacOS. |
| 608 | 611 |
| 609 // Check if we have space on the stack for registers. | 612 // Check if we have space on the stack for registers. |
| 610 Label retry_stack_check; | 613 Label retry_stack_check; |
| 611 Label stack_limit_hit; | 614 Label stack_limit_hit; |
| 612 Label stack_ok; | 615 Label stack_ok; |
| 613 | 616 |
| 614 __ bind(&retry_stack_check); | 617 __ bind(&retry_stack_check); |
| 615 ExternalReference stack_guard_limit = | 618 ExternalReference stack_guard_limit = |
| 616 ExternalReference::address_of_stack_guard_limit(); | 619 ExternalReference::address_of_stack_guard_limit(); |
| 617 __ mov(ecx, esp); | 620 __ mov(ecx, esp); |
| 618 __ sub(ecx, Operand::StaticVariable(stack_guard_limit)); | 621 __ sub(ecx, Operand::StaticVariable(stack_guard_limit)); |
| 619 // Handle it if the stack pointer is already below the stack limit. | 622 // Handle it if the stack pointer is already below the stack limit. |
| 620 __ j(below_equal, &stack_limit_hit, not_taken); | 623 __ j(below_equal, &stack_limit_hit, not_taken); |
| 621 // Check if there is room for the variable number of registers above | 624 // Check if there is room for the variable number of registers above |
| 622 // the stack limit. | 625 // the stack limit. |
| 623 __ cmp(ecx, num_registers_ * kPointerSize); | 626 __ cmp(ecx, num_registers_ * kPointerSize); |
| 624 __ j(above_equal, &stack_ok, taken); | 627 __ j(above_equal, &stack_ok, taken); |
| 625 // Exit with exception. | 628 // Exit with exception. |
| 626 __ mov(eax, EXCEPTION); | 629 __ mov(eax, EXCEPTION); |
| 627 Label exit_without_leave; | 630 __ jmp(&exit_label_); |
| 628 __ jmp(&exit_without_leave); | |
| 629 | 631 |
| 630 __ bind(&stack_limit_hit); | 632 __ bind(&stack_limit_hit); |
| 631 int num_arguments = 2; | 633 int num_arguments = 2; |
| 632 FrameAlign(num_arguments); | 634 FrameAlign(num_arguments); |
| 633 __ mov(Operand(esp, 1 * kPointerSize), Immediate(self_)); | 635 __ mov(Operand(esp, 1 * kPointerSize), Immediate(self_)); |
| 634 __ lea(eax, Operand(esp, -kPointerSize)); | 636 __ lea(eax, Operand(esp, -kPointerSize)); |
| 635 __ mov(Operand(esp, 0 * kPointerSize), eax); | 637 __ mov(Operand(esp, 0 * kPointerSize), eax); |
| 636 CallCFunction(FUNCTION_ADDR(&CheckStackGuardState), num_arguments); | 638 CallCFunction(FUNCTION_ADDR(&CheckStackGuardState), num_arguments); |
| 637 __ or_(eax, Operand(eax)); | 639 __ or_(eax, Operand(eax)); |
| 638 // If returned value is non-zero, the stack guard reports the actual | 640 // If returned value is non-zero, the stack guard reports the actual |
| 639 // stack limit being hit and an exception has already been raised. | 641 // stack limit being hit and an exception has already been raised. |
| 640 // Otherwise it was a preemption and we just check the limit again. | 642 // Otherwise it was a preemption and we just check the limit again. |
| 641 __ j(equal, &retry_stack_check); | 643 __ j(equal, &retry_stack_check); |
| 642 // Return value was non-zero. Exit with exception. | 644 // Return value was non-zero. Exit with exception. |
| 643 __ mov(eax, EXCEPTION); | 645 __ mov(eax, EXCEPTION); |
| 644 __ jmp(&exit_without_leave); | 646 __ jmp(&exit_label_); |
| 645 | 647 |
| 646 __ bind(&stack_ok); | 648 __ bind(&stack_ok); |
| 647 | 649 |
| 648 // Allocate space on stack for registers. | 650 // Allocate space on stack for registers. |
| 649 __ enter(Immediate(num_registers_ * kPointerSize)); | 651 __ sub(Operand(esp), Immediate(num_registers_ * kPointerSize)); |
| 650 // Load string length. | 652 // Load string length. |
| 651 __ mov(esi, Operand(ebp, kInputEndOffset)); | 653 __ mov(esi, Operand(ebp, kInputEndOffset)); |
| 652 // Load input position. | 654 // Load input position. |
| 653 __ mov(edi, Operand(ebp, kInputStartOffset)); | 655 __ mov(edi, Operand(ebp, kInputStartOffset)); |
| 654 // Set up edi to be negative offset from string end. | 656 // Set up edi to be negative offset from string end. |
| 655 __ sub(edi, Operand(esi)); | 657 __ sub(edi, Operand(esi)); |
| 656 // Set up esi to be end of string. First get location. | 658 // Set up esi to be end of string. First get location. |
| 657 __ mov(edx, Operand(ebp, kInputBuffer)); | 659 __ mov(edx, Operand(ebp, kInputBuffer)); |
| 658 // Dereference location to get string start. | 660 // Dereference location to get string start. |
| 659 __ mov(edx, Operand(edx, 0)); | 661 __ mov(edx, Operand(edx, 0)); |
| 660 // Add start to length to complete esi setup. | 662 // Add start to length to complete esi setup. |
| 661 __ add(esi, Operand(edx)); | 663 __ add(esi, Operand(edx)); |
| 662 if (num_saved_registers_ > 0) { | 664 if (num_saved_registers_ > 0) { |
| 663 // Fill saved registers with initial value = start offset - 1 | 665 // Fill saved registers with initial value = start offset - 1 |
| 664 // Fill in stack push order, to avoid accessing across an unwritten | 666 // Fill in stack push order, to avoid accessing across an unwritten |
| 665 // page (a problem on Windows). | 667 // page (a problem on Windows). |
| 666 const int kRegisterZeroEBPOffset = -1; | 668 __ mov(ecx, kRegisterZero); |
| 667 __ mov(ecx, kRegisterZeroEBPOffset); | 669 // Set eax to address of char before start of input |
| 668 // Set eax to address of char before start of input. | 670 // (effectively string position -1). |
| 669 __ lea(eax, Operand(edi, -char_size())); | 671 __ lea(eax, Operand(edi, -char_size())); |
| 670 Label init_loop; | 672 Label init_loop; |
| 671 __ bind(&init_loop); | 673 __ bind(&init_loop); |
| 672 __ mov(Operand(ebp, ecx, times_4, +0), eax); | 674 __ mov(Operand(ebp, ecx, times_1, +0), eax); |
| 673 __ sub(Operand(ecx), Immediate(1)); | 675 __ sub(Operand(ecx), Immediate(kPointerSize)); |
| 674 __ cmp(ecx, -num_saved_registers_); | 676 __ cmp(ecx, kRegisterZero - num_saved_registers_ * kPointerSize); |
| 675 __ j(greater_equal, &init_loop); | 677 __ j(greater, &init_loop); |
| 676 } | 678 } |
| 677 // Ensure that we have written to each stack page. Skipping a page on | 679 // Ensure that we have written to each stack page, in order. Skipping a page |
| 678 // Windows can cause segmentation faults. Assuming page size is 4k. | 680 // on Windows can cause segmentation faults. Assuming page size is 4k. |
| 679 const int kPageSize = 4096; | 681 const int kPageSize = 4096; |
| 680 const int kRegistersPerPage = kPageSize / kPointerSize; | 682 const int kRegistersPerPage = kPageSize / kPointerSize; |
| 681 for (int i = num_saved_registers_ + kRegistersPerPage - 1; | 683 for (int i = num_saved_registers_ + kRegistersPerPage - 1; |
| 682 i < num_registers_; | 684 i < num_registers_; |
| 683 i += kRegistersPerPage) { | 685 i += kRegistersPerPage) { |
| 684 __ mov(register_location(i), eax); // One write every page. | 686 __ mov(register_location(i), eax); // One write every page. |
| 685 } | 687 } |
| 686 | 688 |
| 687 | 689 |
| 688 // Initialize backtrack stack pointer. | 690 // Initialize backtrack stack pointer. |
| 689 __ mov(backtrack_stackpointer(), Operand(ebp, kStackHighEnd)); | 691 __ mov(backtrack_stackpointer(), Operand(ebp, kStackHighEnd)); |
| 690 // Load previous char as initial value of current-character. | 692 // Load previous char as initial value of current-character. |
| 691 Label at_start; | 693 Label at_start; |
| 692 __ cmp(Operand(ebp, kAtStart), Immediate(0)); | 694 __ cmp(Operand(ebp, kAtStart), Immediate(0)); |
| 693 __ j(not_equal, &at_start); | 695 __ j(not_equal, &at_start); |
| 694 LoadCurrentCharacterUnchecked(-1, 1); // Load previous char. | 696 LoadCurrentCharacterUnchecked(-1, 1); // Load previous char. |
| 695 __ jmp(&start_label_); | 697 __ jmp(&start_label_); |
| 696 __ bind(&at_start); | 698 __ bind(&at_start); |
| 697 __ mov(current_character(), '\n'); | 699 __ mov(current_character(), '\n'); |
| 698 __ jmp(&start_label_); | 700 __ jmp(&start_label_); |
| 699 | 701 |
| 700 | 702 |
| 701 // Exit code: | 703 // Exit code: |
| 702 if (success_label_.is_linked()) { | 704 if (success_label_.is_linked()) { |
| 703 // Success | 705 // Save captures when successful. |
| 704 __ bind(&success_label_); | 706 __ bind(&success_label_); |
| 705 if (num_saved_registers_ > 0) { | 707 if (num_saved_registers_ > 0) { |
| 706 // copy captures to output | 708 // copy captures to output |
| 707 __ mov(ebx, Operand(ebp, kRegisterOutput)); | 709 __ mov(ebx, Operand(ebp, kRegisterOutput)); |
| 708 __ mov(ecx, Operand(ebp, kInputEndOffset)); | 710 __ mov(ecx, Operand(ebp, kInputEndOffset)); |
| 709 __ sub(ecx, Operand(ebp, kInputStartOffset)); | 711 __ sub(ecx, Operand(ebp, kInputStartOffset)); |
| 710 for (int i = 0; i < num_saved_registers_; i++) { | 712 for (int i = 0; i < num_saved_registers_; i++) { |
| 711 __ mov(eax, register_location(i)); | 713 __ mov(eax, register_location(i)); |
| 712 __ add(eax, Operand(ecx)); // Convert to index from start, not end. | 714 __ add(eax, Operand(ecx)); // Convert to index from start, not end. |
| 713 if (mode_ == UC16) { | 715 if (mode_ == UC16) { |
| 714 __ sar(eax, 1); // Convert byte index to character index. | 716 __ sar(eax, 1); // Convert byte index to character index. |
| 715 } | 717 } |
| 716 __ mov(Operand(ebx, i * kPointerSize), eax); | 718 __ mov(Operand(ebx, i * kPointerSize), eax); |
| 717 } | 719 } |
| 718 } | 720 } |
| 719 __ mov(eax, Immediate(SUCCESS)); | 721 __ mov(eax, Immediate(SUCCESS)); |
| 720 } | 722 } |
| 721 // Exit and return eax | 723 // Exit and return eax |
| 722 __ bind(&exit_label_); | 724 __ bind(&exit_label_); |
| 723 __ leave(); | 725 // Skip esp past regexp registers. |
| 724 __ bind(&exit_without_leave); // For exiting before doing enter. | 726 __ lea(esp, Operand(ebp, kBackup_ebx)); |
| 727 // Restore callee-save registers. |
| 725 __ pop(ebx); | 728 __ pop(ebx); |
| 726 __ pop(edi); | 729 __ pop(edi); |
| 727 __ pop(esi); | 730 __ pop(esi); |
| 731 // Exit function frame, restore previus one. |
| 732 __ pop(ebp); |
| 728 __ ret(0); | 733 __ ret(0); |
| 729 | 734 |
| 730 // Backtrack code (branch target for conditional backtracks). | 735 // Backtrack code (branch target for conditional backtracks). |
| 731 if (backtrack_label_.is_linked()) { | 736 if (backtrack_label_.is_linked()) { |
| 732 __ bind(&backtrack_label_); | 737 __ bind(&backtrack_label_); |
| 733 Backtrack(); | 738 Backtrack(); |
| 734 } | 739 } |
| 735 | 740 |
| 736 Label exit_with_exception; | 741 Label exit_with_exception; |
| 737 | 742 |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1036 } | 1041 } |
| 1037 return stack_top + (new_stack_end - old_stack_end); | 1042 return stack_top + (new_stack_end - old_stack_end); |
| 1038 } | 1043 } |
| 1039 | 1044 |
| 1040 | 1045 |
| 1041 Operand RegExpMacroAssemblerIA32::register_location(int register_index) { | 1046 Operand RegExpMacroAssemblerIA32::register_location(int register_index) { |
| 1042 ASSERT(register_index < (1<<30)); | 1047 ASSERT(register_index < (1<<30)); |
| 1043 if (num_registers_ <= register_index) { | 1048 if (num_registers_ <= register_index) { |
| 1044 num_registers_ = register_index + 1; | 1049 num_registers_ = register_index + 1; |
| 1045 } | 1050 } |
| 1046 return Operand(ebp, -(register_index + 1) * kPointerSize); | 1051 return Operand(ebp, kRegisterZero - register_index * kPointerSize); |
| 1047 } | 1052 } |
| 1048 | 1053 |
| 1049 | 1054 |
| 1050 void RegExpMacroAssemblerIA32::CheckPosition(int cp_offset, | 1055 void RegExpMacroAssemblerIA32::CheckPosition(int cp_offset, |
| 1051 Label* on_outside_input) { | 1056 Label* on_outside_input) { |
| 1052 __ cmp(edi, -cp_offset * char_size()); | 1057 __ cmp(edi, -cp_offset * char_size()); |
| 1053 BranchOrBacktrack(greater_equal, on_outside_input); | 1058 BranchOrBacktrack(greater_equal, on_outside_input); |
| 1054 } | 1059 } |
| 1055 | 1060 |
| 1056 | 1061 |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1194 | 1199 |
| 1195 | 1200 |
| 1196 void RegExpMacroAssemblerIA32::LoadConstantBufferAddress(Register reg, | 1201 void RegExpMacroAssemblerIA32::LoadConstantBufferAddress(Register reg, |
| 1197 ArraySlice* buffer) { | 1202 ArraySlice* buffer) { |
| 1198 __ mov(reg, buffer->array()); | 1203 __ mov(reg, buffer->array()); |
| 1199 __ add(Operand(reg), Immediate(buffer->base_offset())); | 1204 __ add(Operand(reg), Immediate(buffer->base_offset())); |
| 1200 } | 1205 } |
| 1201 | 1206 |
| 1202 #undef __ | 1207 #undef __ |
| 1203 }} // namespace v8::internal | 1208 }} // namespace v8::internal |
| OLD | NEW |