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 |