| OLD | NEW |
| 1 // Copyright 2008-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2008-2009 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 * - esi : end of input (points to byte after last character in input). | 47 * - esi : end of input (points to byte after last character in input). |
| 48 * - ebp : frame pointer. Used to access arguments, local variables and | 48 * - ebp : frame pointer. Used to access arguments, local variables and |
| 49 * RegExp registers. | 49 * RegExp registers. |
| 50 * - esp : points to tip of C stack. | 50 * - esp : points to tip of C stack. |
| 51 * - ecx : points to tip of backtrack stack | 51 * - ecx : points to tip of backtrack stack |
| 52 * | 52 * |
| 53 * The registers eax, ebx and ecx are free to use for computations. | 53 * The registers eax, ebx and ecx are free to use for computations. |
| 54 * | 54 * |
| 55 * Each call to a public method should retain this convention. | 55 * Each call to a public method should retain this convention. |
| 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_base (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 (Address of end of string) | 61 * - end of input (Address of end of string) |
| 62 * - start of input (Address of first character in string) | 62 * - start of input (Address of first character in string) |
| 63 * - void* input_string (location of a handle containing the string) | 63 * - void* input_string (location of a handle containing the string) |
| 64 * --- frame alignment (if applicable) --- | 64 * --- frame alignment (if applicable) --- |
| 65 * - return address | 65 * - return address |
| 66 * ebp-> - old ebp | 66 * ebp-> - old ebp |
| 67 * - backup of caller esi | 67 * - backup of caller esi |
| 68 * - backup of caller edi | 68 * - backup of caller edi |
| 69 * - backup of caller ebx | 69 * - backup of caller ebx |
| 70 * - Offset of location before start of input (effectively character | 70 * - Offset of location before start of input (effectively character |
| 71 * position -1). Used to initialize capture registers to a non-position. | 71 * position -1). Used to initialize capture registers to a non-position. |
| 72 * - register 0 ebp[-4] (Only positions must be stored in the first | 72 * - register 0 ebp[-4] (Only positions must be stored in the first |
| 73 * - register 1 ebp[-8] num_saved_registers_ registers) | 73 * - register 1 ebp[-8] num_saved_registers_ registers) |
| 74 * - ... | 74 * - ... |
| 75 * | 75 * |
| 76 * The first num_saved_registers_ registers are initialized to point to | 76 * The first num_saved_registers_ registers are initialized to point to |
| 77 * "character -1" in the string (i.e., char_size() bytes before the first | 77 * "character -1" in the string (i.e., char_size() bytes before the first |
| 78 * character of the string). The remaining registers starts out as garbage. | 78 * character of the string). The remaining registers starts out as garbage. |
| 79 * | 79 * |
| 80 * The data up to the return address must be placed there by the calling | 80 * The data up to the return address must be placed there by the calling |
| 81 * code, e.g., by calling the code entry as cast to: | 81 * code, by calling the code entry as cast to a function with the signature: |
| 82 * int (*match)(String* input_string, | 82 * int (*match)(String* input_string, |
| 83 * Address start, | 83 * Address start, |
| 84 * Address end, | 84 * Address end, |
| 85 * int* capture_output_array, | 85 * int* capture_output_array, |
| 86 * bool at_start, | 86 * bool at_start, |
| 87 * byte* stack_area_top) | 87 * byte* stack_area_base) |
| 88 */ | 88 */ |
| 89 | 89 |
| 90 #define __ ACCESS_MASM(masm_) | 90 #define __ ACCESS_MASM(masm_) |
| 91 | 91 |
| 92 RegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32( | 92 RegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32( |
| 93 Mode mode, | 93 Mode mode, |
| 94 int registers_to_save) | 94 int registers_to_save) |
| 95 : masm_(new MacroAssembler(NULL, kRegExpCodeSize)), | 95 : masm_(new MacroAssembler(NULL, kRegExpCodeSize)), |
| 96 constants_(kRegExpConstantsSize), | |
| 97 mode_(mode), | 96 mode_(mode), |
| 98 num_registers_(registers_to_save), | 97 num_registers_(registers_to_save), |
| 99 num_saved_registers_(registers_to_save), | 98 num_saved_registers_(registers_to_save), |
| 100 entry_label_(), | 99 entry_label_(), |
| 101 start_label_(), | 100 start_label_(), |
| 102 success_label_(), | 101 success_label_(), |
| 103 backtrack_label_(), | 102 backtrack_label_(), |
| 104 exit_label_() { | 103 exit_label_() { |
| 105 __ jmp(&entry_label_); // We'll write the entry code later. | 104 __ jmp(&entry_label_); // We'll write the entry code later. |
| 106 __ bind(&start_label_); // And then continue from here. | 105 __ bind(&start_label_); // And then continue from here. |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 149 __ add(Operand(ebx), Immediate(masm_->CodeObject())); | 148 __ add(Operand(ebx), Immediate(masm_->CodeObject())); |
| 150 __ jmp(Operand(ebx)); | 149 __ jmp(Operand(ebx)); |
| 151 } | 150 } |
| 152 | 151 |
| 153 | 152 |
| 154 void RegExpMacroAssemblerIA32::Bind(Label* label) { | 153 void RegExpMacroAssemblerIA32::Bind(Label* label) { |
| 155 __ bind(label); | 154 __ bind(label); |
| 156 } | 155 } |
| 157 | 156 |
| 158 | 157 |
| 159 void RegExpMacroAssemblerIA32::CheckBitmap(uc16 start, | |
| 160 Label* bitmap, | |
| 161 Label* on_zero) { | |
| 162 UNIMPLEMENTED(); | |
| 163 } | |
| 164 | |
| 165 | |
| 166 void RegExpMacroAssemblerIA32::CheckCharacter(uint32_t c, Label* on_equal) { | 158 void RegExpMacroAssemblerIA32::CheckCharacter(uint32_t c, Label* on_equal) { |
| 167 __ cmp(current_character(), c); | 159 __ cmp(current_character(), c); |
| 168 BranchOrBacktrack(equal, on_equal); | 160 BranchOrBacktrack(equal, on_equal); |
| 169 } | 161 } |
| 170 | 162 |
| 171 | 163 |
| 172 void RegExpMacroAssemblerIA32::CheckCharacterGT(uc16 limit, Label* on_greater) { | 164 void RegExpMacroAssemblerIA32::CheckCharacterGT(uc16 limit, Label* on_greater) { |
| 173 __ cmp(current_character(), limit); | 165 __ cmp(current_character(), limit); |
| 174 BranchOrBacktrack(greater, on_greater); | 166 BranchOrBacktrack(greater, on_greater); |
| 175 } | 167 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 Label* on_failure, | 202 Label* on_failure, |
| 211 bool check_end_of_string) { | 203 bool check_end_of_string) { |
| 212 int byte_length = str.length() * char_size(); | 204 int byte_length = str.length() * char_size(); |
| 213 int byte_offset = cp_offset * char_size(); | 205 int byte_offset = cp_offset * char_size(); |
| 214 if (check_end_of_string) { | 206 if (check_end_of_string) { |
| 215 // Check that there are at least str.length() characters left in the input. | 207 // Check that there are at least str.length() characters left in the input. |
| 216 __ cmp(Operand(edi), Immediate(-(byte_offset + byte_length))); | 208 __ cmp(Operand(edi), Immediate(-(byte_offset + byte_length))); |
| 217 BranchOrBacktrack(greater, on_failure); | 209 BranchOrBacktrack(greater, on_failure); |
| 218 } | 210 } |
| 219 | 211 |
| 220 Label backtrack; | |
| 221 if (on_failure == NULL) { | 212 if (on_failure == NULL) { |
| 222 // Avoid inlining the Backtrack macro for each test. | 213 // Instead of inlining a backtrack, (re)use the global backtrack target. |
| 223 Label skip_backtrack; | 214 on_failure = &backtrack_label_; |
| 224 __ jmp(&skip_backtrack); | |
| 225 __ bind(&backtrack); | |
| 226 Backtrack(); | |
| 227 __ bind(&skip_backtrack); | |
| 228 on_failure = &backtrack; | |
| 229 } | 215 } |
| 230 | 216 |
| 231 for (int i = 0; i < str.length(); i++) { | 217 for (int i = 0; i < str.length(); i++) { |
| 232 if (mode_ == ASCII) { | 218 if (mode_ == ASCII) { |
| 233 __ cmpb(Operand(esi, edi, times_1, byte_offset + i), | 219 __ cmpb(Operand(esi, edi, times_1, byte_offset + i), |
| 234 static_cast<int8_t>(str[i])); | 220 static_cast<int8_t>(str[i])); |
| 235 } else { | 221 } else { |
| 236 ASSERT(mode_ == UC16); | 222 ASSERT(mode_ == UC16); |
| 237 __ cmpw(Operand(esi, edi, times_1, byte_offset + i * sizeof(uc16)), | 223 __ cmpw(Operand(esi, edi, times_1, byte_offset + i * sizeof(uc16)), |
| 238 Immediate(str[i])); | 224 Immediate(str[i])); |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 574 if (check_offset) { | 560 if (check_offset) { |
| 575 CheckPosition(cp_offset, on_no_match); | 561 CheckPosition(cp_offset, on_no_match); |
| 576 } | 562 } |
| 577 return true; | 563 return true; |
| 578 // No custom implementation (yet): w, W, s(UC16), S(UC16). | 564 // No custom implementation (yet): w, W, s(UC16), S(UC16). |
| 579 default: | 565 default: |
| 580 return false; | 566 return false; |
| 581 } | 567 } |
| 582 } | 568 } |
| 583 | 569 |
| 584 void RegExpMacroAssemblerIA32::DispatchHalfNibbleMap( | |
| 585 uc16 start, | |
| 586 Label* half_nibble_map, | |
| 587 const Vector<Label*>& destinations) { | |
| 588 UNIMPLEMENTED(); | |
| 589 } | |
| 590 | |
| 591 | |
| 592 void RegExpMacroAssemblerIA32::DispatchByteMap( | |
| 593 uc16 start, | |
| 594 Label* byte_map, | |
| 595 const Vector<Label*>& destinations) { | |
| 596 UNIMPLEMENTED(); | |
| 597 } | |
| 598 | |
| 599 | |
| 600 void RegExpMacroAssemblerIA32::DispatchHighByteMap( | |
| 601 byte start, | |
| 602 Label* byte_map, | |
| 603 const Vector<Label*>& destinations) { | |
| 604 UNIMPLEMENTED(); | |
| 605 } | |
| 606 | |
| 607 | |
| 608 void RegExpMacroAssemblerIA32::EmitOrLink(Label* label) { | |
| 609 UNIMPLEMENTED(); // Has no use. | |
| 610 } | |
| 611 | |
| 612 | 570 |
| 613 void RegExpMacroAssemblerIA32::Fail() { | 571 void RegExpMacroAssemblerIA32::Fail() { |
| 614 ASSERT(FAILURE == 0); // Return value for failure is zero. | 572 ASSERT(FAILURE == 0); // Return value for failure is zero. |
| 615 __ xor_(eax, Operand(eax)); // zero eax. | 573 __ xor_(eax, Operand(eax)); // zero eax. |
| 616 __ jmp(&exit_label_); | 574 __ jmp(&exit_label_); |
| 617 } | 575 } |
| 618 | 576 |
| 619 | 577 |
| 620 Handle<Object> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) { | 578 Handle<Object> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) { |
| 621 // Finalize code - write the entry point code now we know how many | 579 // Finalize code - write the entry point code now we know how many |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 661 __ bind(&stack_ok); | 619 __ bind(&stack_ok); |
| 662 | 620 |
| 663 // Allocate space on stack for registers. | 621 // Allocate space on stack for registers. |
| 664 __ sub(Operand(esp), Immediate(num_registers_ * kPointerSize)); | 622 __ sub(Operand(esp), Immediate(num_registers_ * kPointerSize)); |
| 665 // Load string length. | 623 // Load string length. |
| 666 __ mov(esi, Operand(ebp, kInputEnd)); | 624 __ mov(esi, Operand(ebp, kInputEnd)); |
| 667 // Load input position. | 625 // Load input position. |
| 668 __ mov(edi, Operand(ebp, kInputStart)); | 626 __ mov(edi, Operand(ebp, kInputStart)); |
| 669 // Set up edi to be negative offset from string end. | 627 // Set up edi to be negative offset from string end. |
| 670 __ sub(edi, Operand(esi)); | 628 __ sub(edi, Operand(esi)); |
| 671 if (num_saved_registers_ > 0) { | 629 // Set eax to address of char before start of input |
| 630 // (effectively string position -1). |
| 631 __ lea(eax, Operand(edi, -char_size())); |
| 632 // Store this value in a local variable, for use when clearing |
| 633 // position registers. |
| 634 __ mov(Operand(ebp, kInputStartMinusOne), eax); |
| 635 if (num_saved_registers_ > 0) { // Always is, if generated from a regexp. |
| 672 // Fill saved registers with initial value = start offset - 1 | 636 // Fill saved registers with initial value = start offset - 1 |
| 673 // Fill in stack push order, to avoid accessing across an unwritten | 637 // Fill in stack push order, to avoid accessing across an unwritten |
| 674 // page (a problem on Windows). | 638 // page (a problem on Windows). |
| 675 __ mov(ecx, kRegisterZero); | 639 __ mov(ecx, kRegisterZero); |
| 676 // Set eax to address of char before start of input | |
| 677 // (effectively string position -1). | |
| 678 __ lea(eax, Operand(edi, -char_size())); | |
| 679 // Store this value in a local variable, for use when clearing | |
| 680 // position registers. | |
| 681 __ mov(Operand(ebp, kInputStartMinusOne), eax); | |
| 682 Label init_loop; | 640 Label init_loop; |
| 683 __ bind(&init_loop); | 641 __ bind(&init_loop); |
| 684 __ mov(Operand(ebp, ecx, times_1, +0), eax); | 642 __ mov(Operand(ebp, ecx, times_1, +0), eax); |
| 685 __ sub(Operand(ecx), Immediate(kPointerSize)); | 643 __ sub(Operand(ecx), Immediate(kPointerSize)); |
| 686 __ cmp(ecx, kRegisterZero - num_saved_registers_ * kPointerSize); | 644 __ cmp(ecx, kRegisterZero - num_saved_registers_ * kPointerSize); |
| 687 __ j(greater, &init_loop); | 645 __ j(greater, &init_loop); |
| 688 } | 646 } |
| 689 // Ensure that we have written to each stack page, in order. Skipping a page | 647 // Ensure that we have written to each stack page, in order. Skipping a page |
| 690 // on Windows can cause segmentation faults. Assuming page size is 4k. | 648 // on Windows can cause segmentation faults. Assuming page size is 4k. |
| 691 const int kPageSize = 4096; | 649 const int kPageSize = 4096; |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 935 } | 893 } |
| 936 | 894 |
| 937 | 895 |
| 938 void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) { | 896 void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) { |
| 939 __ mov(eax, backtrack_stackpointer()); | 897 __ mov(eax, backtrack_stackpointer()); |
| 940 __ sub(eax, Operand(ebp, kStackHighEnd)); | 898 __ sub(eax, Operand(ebp, kStackHighEnd)); |
| 941 __ mov(register_location(reg), eax); | 899 __ mov(register_location(reg), eax); |
| 942 } | 900 } |
| 943 | 901 |
| 944 | 902 |
| 945 RegExpMacroAssemblerIA32::Result RegExpMacroAssemblerIA32::Match( | |
| 946 Handle<Code> regexp_code, | |
| 947 Handle<String> subject, | |
| 948 int* offsets_vector, | |
| 949 int offsets_vector_length, | |
| 950 int previous_index) { | |
| 951 | |
| 952 ASSERT(subject->IsFlat()); | |
| 953 ASSERT(previous_index >= 0); | |
| 954 ASSERT(previous_index <= subject->length()); | |
| 955 | |
| 956 // No allocations before calling the regexp, but we can't use | |
| 957 // AssertNoAllocation, since regexps might be preempted, and another thread | |
| 958 // might do allocation anyway. | |
| 959 | |
| 960 String* subject_ptr = *subject; | |
| 961 // Character offsets into string. | |
| 962 int start_offset = previous_index; | |
| 963 int end_offset = subject_ptr->length(); | |
| 964 | |
| 965 bool is_ascii = subject->IsAsciiRepresentation(); | |
| 966 | |
| 967 if (StringShape(subject_ptr).IsCons()) { | |
| 968 subject_ptr = ConsString::cast(subject_ptr)->first(); | |
| 969 } else if (StringShape(subject_ptr).IsSliced()) { | |
| 970 SlicedString* slice = SlicedString::cast(subject_ptr); | |
| 971 start_offset += slice->start(); | |
| 972 end_offset += slice->start(); | |
| 973 subject_ptr = slice->buffer(); | |
| 974 } | |
| 975 // Ensure that an underlying string has the same ascii-ness. | |
| 976 ASSERT(subject_ptr->IsAsciiRepresentation() == is_ascii); | |
| 977 ASSERT(subject_ptr->IsExternalString() || subject_ptr->IsSeqString()); | |
| 978 // String is now either Sequential or External | |
| 979 int char_size_shift = is_ascii ? 0 : 1; | |
| 980 int char_length = end_offset - start_offset; | |
| 981 | |
| 982 const byte* input_start = | |
| 983 StringCharacterPosition(subject_ptr, start_offset); | |
| 984 int byte_length = char_length << char_size_shift; | |
| 985 const byte* input_end = input_start + byte_length; | |
| 986 RegExpMacroAssemblerIA32::Result res = Execute(*regexp_code, | |
| 987 subject_ptr, | |
| 988 start_offset, | |
| 989 input_start, | |
| 990 input_end, | |
| 991 offsets_vector, | |
| 992 previous_index == 0); | |
| 993 | |
| 994 if (res == SUCCESS) { | |
| 995 // Capture values are relative to start_offset only. | |
| 996 // Convert them to be relative to start of string. | |
| 997 for (int i = 0; i < offsets_vector_length; i++) { | |
| 998 if (offsets_vector[i] >= 0) { | |
| 999 offsets_vector[i] += previous_index; | |
| 1000 } | |
| 1001 } | |
| 1002 } | |
| 1003 | |
| 1004 return res; | |
| 1005 } | |
| 1006 | |
| 1007 // Private methods: | 903 // Private methods: |
| 1008 | 904 |
| 1009 static unibrow::Mapping<unibrow::Ecma262Canonicalize> canonicalize; | |
| 1010 | |
| 1011 RegExpMacroAssemblerIA32::Result RegExpMacroAssemblerIA32::Execute( | |
| 1012 Code* code, | |
| 1013 String* input, | |
| 1014 int start_offset, | |
| 1015 const byte* input_start, | |
| 1016 const byte* input_end, | |
| 1017 int* output, | |
| 1018 bool at_start) { | |
| 1019 typedef int (*matcher)(String*, int, const byte*, | |
| 1020 const byte*, int*, int, Address); | |
| 1021 matcher matcher_func = FUNCTION_CAST<matcher>(code->entry()); | |
| 1022 | |
| 1023 int at_start_val = at_start ? 1 : 0; | |
| 1024 | |
| 1025 // Ensure that the minimum stack has been allocated. | |
| 1026 RegExpStack stack; | |
| 1027 Address stack_top = RegExpStack::stack_top(); | |
| 1028 | |
| 1029 int result = matcher_func(input, | |
| 1030 start_offset, | |
| 1031 input_start, | |
| 1032 input_end, | |
| 1033 output, | |
| 1034 at_start_val, | |
| 1035 stack_top); | |
| 1036 ASSERT(result <= SUCCESS); | |
| 1037 ASSERT(result >= RETRY); | |
| 1038 | |
| 1039 if (result == EXCEPTION && !Top::has_pending_exception()) { | |
| 1040 // We detected a stack overflow (on the backtrack stack) in RegExp code, | |
| 1041 // but haven't created the exception yet. | |
| 1042 Top::StackOverflow(); | |
| 1043 } | |
| 1044 return static_cast<Result>(result); | |
| 1045 } | |
| 1046 | |
| 1047 | |
| 1048 int RegExpMacroAssemblerIA32::CaseInsensitiveCompareUC16(Address byte_offset1, | |
| 1049 Address byte_offset2, | |
| 1050 size_t byte_length) { | |
| 1051 // This function is not allowed to cause a garbage collection. | |
| 1052 // A GC might move the calling generated code and invalidate the | |
| 1053 // return address on the stack. | |
| 1054 ASSERT(byte_length % 2 == 0); | |
| 1055 uc16* substring1 = reinterpret_cast<uc16*>(byte_offset1); | |
| 1056 uc16* substring2 = reinterpret_cast<uc16*>(byte_offset2); | |
| 1057 size_t length = byte_length >> 1; | |
| 1058 | |
| 1059 for (size_t i = 0; i < length; i++) { | |
| 1060 unibrow::uchar c1 = substring1[i]; | |
| 1061 unibrow::uchar c2 = substring2[i]; | |
| 1062 if (c1 != c2) { | |
| 1063 unibrow::uchar s1[1] = { c1 }; | |
| 1064 canonicalize.get(c1, '\0', s1); | |
| 1065 if (s1[0] != c2) { | |
| 1066 unibrow::uchar s2[1] = { c2 }; | |
| 1067 canonicalize.get(c2, '\0', s2); | |
| 1068 if (s1[0] != s2[0]) { | |
| 1069 return 0; | |
| 1070 } | |
| 1071 } | |
| 1072 } | |
| 1073 } | |
| 1074 return 1; | |
| 1075 } | |
| 1076 | |
| 1077 | |
| 1078 void RegExpMacroAssemblerIA32::CallCheckStackGuardState(Register scratch) { | 905 void RegExpMacroAssemblerIA32::CallCheckStackGuardState(Register scratch) { |
| 1079 int num_arguments = 3; | 906 int num_arguments = 3; |
| 1080 FrameAlign(num_arguments, scratch); | 907 FrameAlign(num_arguments, scratch); |
| 1081 // RegExp code frame pointer. | 908 // RegExp code frame pointer. |
| 1082 __ mov(Operand(esp, 2 * kPointerSize), ebp); | 909 __ mov(Operand(esp, 2 * kPointerSize), ebp); |
| 1083 // Code* of self. | 910 // Code* of self. |
| 1084 __ mov(Operand(esp, 1 * kPointerSize), Immediate(masm_->CodeObject())); | 911 __ mov(Operand(esp, 1 * kPointerSize), Immediate(masm_->CodeObject())); |
| 1085 // Next address on the stack (will be address of return address). | 912 // Next address on the stack (will be address of return address). |
| 1086 __ lea(eax, Operand(esp, -kPointerSize)); | 913 __ lea(eax, Operand(esp, -kPointerSize)); |
| 1087 __ mov(Operand(esp, 0 * kPointerSize), eax); | 914 __ mov(Operand(esp, 0 * kPointerSize), eax); |
| 1088 CallCFunction(FUNCTION_ADDR(&CheckStackGuardState), num_arguments); | 915 CallCFunction(FUNCTION_ADDR(&CheckStackGuardState), num_arguments); |
| 1089 } | 916 } |
| 1090 | 917 |
| 1091 | 918 |
| 1092 // Helper function for reading a value out of a stack frame. | 919 // Helper function for reading a value out of a stack frame. |
| 1093 template <typename T> | 920 template <typename T> |
| 1094 static T& frame_entry(Address re_frame, int frame_offset) { | 921 static T& frame_entry(Address re_frame, int frame_offset) { |
| 1095 return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset)); | 922 return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset)); |
| 1096 } | 923 } |
| 1097 | 924 |
| 1098 | 925 |
| 1099 const byte* RegExpMacroAssemblerIA32::StringCharacterPosition(String* subject, | |
| 1100 int start_index) { | |
| 1101 // Not just flat, but ultra flat. | |
| 1102 ASSERT(subject->IsExternalString() || subject->IsSeqString()); | |
| 1103 ASSERT(start_index >= 0); | |
| 1104 ASSERT(start_index <= subject->length()); | |
| 1105 if (subject->IsAsciiRepresentation()) { | |
| 1106 const byte* address; | |
| 1107 if (StringShape(subject).IsExternal()) { | |
| 1108 const char* data = ExternalAsciiString::cast(subject)->resource()->data(); | |
| 1109 address = reinterpret_cast<const byte*>(data); | |
| 1110 } else { | |
| 1111 ASSERT(subject->IsSeqAsciiString()); | |
| 1112 char* data = SeqAsciiString::cast(subject)->GetChars(); | |
| 1113 address = reinterpret_cast<const byte*>(data); | |
| 1114 } | |
| 1115 return address + start_index; | |
| 1116 } | |
| 1117 const uc16* data; | |
| 1118 if (StringShape(subject).IsExternal()) { | |
| 1119 data = ExternalTwoByteString::cast(subject)->resource()->data(); | |
| 1120 } else { | |
| 1121 ASSERT(subject->IsSeqTwoByteString()); | |
| 1122 data = SeqTwoByteString::cast(subject)->GetChars(); | |
| 1123 } | |
| 1124 return reinterpret_cast<const byte*>(data + start_index); | |
| 1125 } | |
| 1126 | |
| 1127 | |
| 1128 int RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address, | 926 int RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address, |
| 1129 Code* re_code, | 927 Code* re_code, |
| 1130 Address re_frame) { | 928 Address re_frame) { |
| 1131 if (StackGuard::IsStackOverflow()) { | 929 if (StackGuard::IsStackOverflow()) { |
| 1132 Top::StackOverflow(); | 930 Top::StackOverflow(); |
| 1133 return EXCEPTION; | 931 return EXCEPTION; |
| 1134 } | 932 } |
| 1135 | 933 |
| 1136 // If not real stack overflow the stack guard was used to interrupt | 934 // If not real stack overflow the stack guard was used to interrupt |
| 1137 // execution for another purpose. | 935 // execution for another purpose. |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1191 frame_entry<const String*>(re_frame, kInputString) = *subject; | 989 frame_entry<const String*>(re_frame, kInputString) = *subject; |
| 1192 frame_entry<const byte*>(re_frame, kInputStart) = new_address; | 990 frame_entry<const byte*>(re_frame, kInputStart) = new_address; |
| 1193 frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length; | 991 frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length; |
| 1194 } | 992 } |
| 1195 | 993 |
| 1196 return 0; | 994 return 0; |
| 1197 } | 995 } |
| 1198 | 996 |
| 1199 | 997 |
| 1200 Address RegExpMacroAssemblerIA32::GrowStack(Address stack_pointer, | 998 Address RegExpMacroAssemblerIA32::GrowStack(Address stack_pointer, |
| 1201 Address* stack_top) { | 999 Address* stack_base) { |
| 1202 size_t size = RegExpStack::stack_capacity(); | 1000 size_t size = RegExpStack::stack_capacity(); |
| 1203 Address old_stack_top = RegExpStack::stack_top(); | 1001 Address old_stack_base = RegExpStack::stack_base(); |
| 1204 ASSERT(old_stack_top == *stack_top); | 1002 ASSERT(old_stack_base == *stack_base); |
| 1205 ASSERT(stack_pointer <= old_stack_top); | 1003 ASSERT(stack_pointer <= old_stack_base); |
| 1206 ASSERT(static_cast<size_t>(old_stack_top - stack_pointer) <= size); | 1004 ASSERT(static_cast<size_t>(old_stack_base - stack_pointer) <= size); |
| 1207 Address new_stack_top = RegExpStack::EnsureCapacity(size * 2); | 1005 Address new_stack_base = RegExpStack::EnsureCapacity(size * 2); |
| 1208 if (new_stack_top == NULL) { | 1006 if (new_stack_base == NULL) { |
| 1209 return NULL; | 1007 return NULL; |
| 1210 } | 1008 } |
| 1211 *stack_top = new_stack_top; | 1009 *stack_base = new_stack_base; |
| 1212 return new_stack_top - (old_stack_top - stack_pointer); | 1010 return new_stack_base - (old_stack_base - stack_pointer); |
| 1213 } | 1011 } |
| 1214 | 1012 |
| 1215 | 1013 |
| 1216 Operand RegExpMacroAssemblerIA32::register_location(int register_index) { | 1014 Operand RegExpMacroAssemblerIA32::register_location(int register_index) { |
| 1217 ASSERT(register_index < (1<<30)); | 1015 ASSERT(register_index < (1<<30)); |
| 1218 if (num_registers_ <= register_index) { | 1016 if (num_registers_ <= register_index) { |
| 1219 num_registers_ = register_index + 1; | 1017 num_registers_ = register_index + 1; |
| 1220 } | 1018 } |
| 1221 return Operand(ebp, kRegisterZero - register_index * kPointerSize); | 1019 return Operand(ebp, kRegisterZero - register_index * kPointerSize); |
| 1222 } | 1020 } |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1366 Operand(esi, edi, times_1, cp_offset * sizeof(uc16))); | 1164 Operand(esi, edi, times_1, cp_offset * sizeof(uc16))); |
| 1367 } else { | 1165 } else { |
| 1368 ASSERT(characters == 1); | 1166 ASSERT(characters == 1); |
| 1369 __ movzx_w(current_character(), | 1167 __ movzx_w(current_character(), |
| 1370 Operand(esi, edi, times_1, cp_offset * sizeof(uc16))); | 1168 Operand(esi, edi, times_1, cp_offset * sizeof(uc16))); |
| 1371 } | 1169 } |
| 1372 } | 1170 } |
| 1373 } | 1171 } |
| 1374 | 1172 |
| 1375 | 1173 |
| 1376 void RegExpMacroAssemblerIA32::LoadConstantBufferAddress(Register reg, | |
| 1377 ArraySlice* buffer) { | |
| 1378 __ mov(reg, buffer->array()); | |
| 1379 __ add(Operand(reg), Immediate(buffer->base_offset())); | |
| 1380 } | |
| 1381 | |
| 1382 #undef __ | 1174 #undef __ |
| 1383 }} // namespace v8::internal | 1175 }} // namespace v8::internal |
| OLD | NEW |