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

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

Issue 18096: Experimental: merge from bleeding_edge. Merge up to and including... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: Created 11 years, 11 months 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 | Annotate | Revision Log
« no previous file with comments | « src/regexp-macro-assembler-ia32.h ('k') | src/regexp-macro-assembler-irregexp.h » ('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 12 matching lines...) Expand all
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include <string.h> 28 #include <string.h>
29 #include "v8.h" 29 #include "v8.h"
30 #include "unicode.h" 30 #include "unicode.h"
31 #include "log.h" 31 #include "log.h"
32 #include "ast.h" 32 #include "ast.h"
33 #include "regexp-stack.h"
33 #include "macro-assembler.h" 34 #include "macro-assembler.h"
34 #include "regexp-macro-assembler.h" 35 #include "regexp-macro-assembler.h"
35 #include "macro-assembler-ia32.h" 36 #include "macro-assembler-ia32.h"
36 #include "regexp-macro-assembler-ia32.h" 37 #include "regexp-macro-assembler-ia32.h"
37 38
38 namespace v8 { namespace internal { 39 namespace v8 { namespace internal {
39 40
40 /* 41 /*
41 * This assembler uses the following register assignment convention 42 * This assembler uses the following register assignment convention
42 * - edx : current character. Must be loaded using LoadCurrentCharacter 43 * - edx : current character. Must be loaded using LoadCurrentCharacter
43 * before using any of the dispatch methods. 44 * before using any of the dispatch methods.
44 * - edi : current position in input, as negative offset from end of string. 45 * - edi : current position in input, as negative offset from end of string.
45 * Please notice that this is the byte offset, not the character offset! 46 * Please notice that this is the byte offset, not the character offset!
46 * - 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).
47 * - ebp : points to the location above the registers on the stack, 48 * - ebp : points to the location above the registers on the stack,
48 * as if by the "enter <register_count>" opcode. 49 * as if by the "enter <register_count>" opcode.
49 * - esp : points to tip of backtracking stack. 50 * - esp : points to tip of C stack.
51 * - ecx : points to tip of backtrack stack
50 * 52 *
51 * 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.
52 * 54 *
53 * Each call to a public method should retain this convention. 55 * Each call to a public method should retain this convention.
54 * 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
58 * backtracking stack)
55 * - 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)
56 * - int* capture_array (int[num_saved_registers_], for output). 60 * - int* capture_array (int[num_saved_registers_], for output).
57 * - 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)
58 * - start of input (index of first character in string, relative 62 * - start of input (index of first character in string, relative
59 * to *string_base) 63 * to *string_base)
60 * - void** string_base (location of a handle containing the string) 64 * - void** string_base (location of a handle containing the string)
61 * - return address 65 * - return address
62 * - backup of esi
63 * - backup of edi
64 * - backup of ebx
65 * ebp-> - old ebp 66 * ebp-> - old ebp
67 * - backup of caller esi
68 * - backup of caller edi
69 * - backup of caller ebx
66 * - 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
67 * - register 1 ebp[-8] num_saved_registers_ registers) 71 * - register 1 ebp[-8] num_saved_registers_ registers)
68 * - ... 72 * - ...
69 * 73 *
70 * The first num_saved_registers_ registers are initialized to point to 74 * The first num_saved_registers_ registers are initialized to point to
71 * "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
72 * character of the string). The remaining registers starts out as garbage. 76 * character of the string). The remaining registers starts out as garbage.
73 * 77 *
74 * 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
75 * code, e.g., by calling the code as cast to: 79 * code, e.g., by calling the code as cast to:
76 * bool (*match)(String** string_base, 80 * bool (*match)(String** string_base,
77 * int start_offset, 81 * int start_offset,
78 * int end_offset, 82 * int end_offset,
79 * int* capture_output_array, 83 * int* capture_output_array,
80 * bool at_start) 84 * bool at_start,
85 * byte* stack_area_top)
81 */ 86 */
82 87
83 #define __ masm_-> 88 #define __ masm_->
84 89
85 RegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32( 90 RegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32(
86 Mode mode, 91 Mode mode,
87 int registers_to_save) 92 int registers_to_save)
88 : masm_(new MacroAssembler(NULL, kRegExpCodeSize)), 93 : masm_(new MacroAssembler(NULL, kRegExpCodeSize)),
89 constants_(kRegExpConstantsSize), 94 constants_(kRegExpConstantsSize),
90 mode_(mode), 95 mode_(mode),
(...skipping 12 matching lines...) Expand all
103 108
104 RegExpMacroAssemblerIA32::~RegExpMacroAssemblerIA32() { 109 RegExpMacroAssemblerIA32::~RegExpMacroAssemblerIA32() {
105 delete masm_; 110 delete masm_;
106 // Unuse labels in case we throw away the assembler without calling GetCode. 111 // Unuse labels in case we throw away the assembler without calling GetCode.
107 entry_label_.Unuse(); 112 entry_label_.Unuse();
108 start_label_.Unuse(); 113 start_label_.Unuse();
109 success_label_.Unuse(); 114 success_label_.Unuse();
110 backtrack_label_.Unuse(); 115 backtrack_label_.Unuse();
111 exit_label_.Unuse(); 116 exit_label_.Unuse();
112 check_preempt_label_.Unuse(); 117 check_preempt_label_.Unuse();
118 stack_overflow_label_.Unuse();
119 }
120
121
122 int RegExpMacroAssemblerIA32::stack_limit_slack() {
123 return RegExpStack::kStackLimitSlack;
113 } 124 }
114 125
115 126
116 void RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) { 127 void RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) {
117 if (by != 0) { 128 if (by != 0) {
118 Label inside_string; 129 Label inside_string;
119 __ add(Operand(edi), Immediate(by * char_size())); 130 __ add(Operand(edi), Immediate(by * char_size()));
120 } 131 }
121 } 132 }
122 133
123 134
124 void RegExpMacroAssemblerIA32::AdvanceRegister(int reg, int by) { 135 void RegExpMacroAssemblerIA32::AdvanceRegister(int reg, int by) {
125 ASSERT(reg >= 0); 136 ASSERT(reg >= 0);
126 ASSERT(reg < num_registers_); 137 ASSERT(reg < num_registers_);
127 __ add(register_location(reg), Immediate(by)); 138 if (by != 0) {
139 __ add(register_location(reg), Immediate(by));
140 }
128 } 141 }
129 142
130 143
131 void RegExpMacroAssemblerIA32::Backtrack() { 144 void RegExpMacroAssemblerIA32::Backtrack() {
132 SafeReturn(); 145 CheckPreemption();
146 // Pop Code* offset from backtrack stack, add Code* and jump to location.
147 Pop(ebx);
148 __ add(Operand(ebx), Immediate(self_));
149 __ jmp(Operand(ebx));
133 } 150 }
134 151
135 152
136 void RegExpMacroAssemblerIA32::Bind(Label* label) { 153 void RegExpMacroAssemblerIA32::Bind(Label* label) {
137 __ bind(label); 154 __ bind(label);
138 } 155 }
139 156
157
140 void RegExpMacroAssemblerIA32::CheckBitmap(uc16 start, 158 void RegExpMacroAssemblerIA32::CheckBitmap(uc16 start,
141 Label* bitmap, 159 Label* bitmap,
142 Label* on_zero) { 160 Label* on_zero) {
143 UNIMPLEMENTED(); 161 UNIMPLEMENTED();
144 __ mov(eax, current_character());
145 __ sub(Operand(eax), Immediate(start));
146 __ cmp(eax, 64); // FIXME: 64 = length_of_bitmap_in_bits.
147 BranchOrBacktrack(greater_equal, on_zero);
148 __ mov(ebx, eax);
149 __ shr(ebx, 3);
150 // TODO(lrn): Where is the bitmap stored? Pass the bitmap as argument instead.
151 // __ mov(ecx, position_of_bitmap);
152 __ movzx_b(ebx, Operand(ecx, ebx, times_1, 0));
153 __ and_(eax, (1<<3)-1);
154 __ bt(Operand(ebx), eax);
155 BranchOrBacktrack(carry, on_zero);
156 } 162 }
157 163
158 164
159 void RegExpMacroAssemblerIA32::CheckCharacter(uint32_t c, Label* on_equal) { 165 void RegExpMacroAssemblerIA32::CheckCharacter(uint32_t c, Label* on_equal) {
160 __ cmp(current_character(), c); 166 __ cmp(current_character(), c);
161 BranchOrBacktrack(equal, on_equal); 167 BranchOrBacktrack(equal, on_equal);
162 } 168 }
163 169
164 170
165 void RegExpMacroAssemblerIA32::CheckCharacterGT(uc16 limit, Label* on_greater) { 171 void RegExpMacroAssemblerIA32::CheckCharacterGT(uc16 limit, Label* on_greater) {
166 __ cmp(current_character(), limit); 172 __ cmp(current_character(), limit);
167 BranchOrBacktrack(greater, on_greater); 173 BranchOrBacktrack(greater, on_greater);
168 } 174 }
169 175
170 176
171 void RegExpMacroAssemblerIA32::CheckNotAtStart(Label* on_not_at_start) { 177 void RegExpMacroAssemblerIA32::CheckNotAtStart(Label* on_not_at_start) {
178 // Did we start the match at the start of the string at all?
172 __ cmp(Operand(ebp, kAtStart), Immediate(0)); 179 __ cmp(Operand(ebp, kAtStart), Immediate(0));
173 BranchOrBacktrack(equal, on_not_at_start); 180 BranchOrBacktrack(equal, on_not_at_start);
181 // If we did, are we still at the start of the input?
174 __ mov(eax, Operand(ebp, kInputEndOffset)); 182 __ mov(eax, Operand(ebp, kInputEndOffset));
175 __ add(eax, Operand(edi)); 183 __ add(eax, Operand(edi));
176 __ cmp(eax, Operand(ebp, kInputStartOffset)); 184 __ cmp(eax, Operand(ebp, kInputStartOffset));
177 BranchOrBacktrack(not_equal, on_not_at_start); 185 BranchOrBacktrack(not_equal, on_not_at_start);
178 } 186 }
179 187
180 188
181 void RegExpMacroAssemblerIA32::CheckCharacterLT(uc16 limit, Label* on_less) { 189 void RegExpMacroAssemblerIA32::CheckCharacterLT(uc16 limit, Label* on_less) {
182 __ cmp(current_character(), limit); 190 __ cmp(current_character(), limit);
183 BranchOrBacktrack(less, on_less); 191 BranchOrBacktrack(less, on_less);
184 } 192 }
185 193
186 194
187 void RegExpMacroAssemblerIA32::CheckCharacters(Vector<const uc16> str, 195 void RegExpMacroAssemblerIA32::CheckCharacters(Vector<const uc16> str,
188 int cp_offset, 196 int cp_offset,
189 Label* on_failure, 197 Label* on_failure,
190 bool check_end_of_string) { 198 bool check_end_of_string) {
191 int byte_length = str.length() * char_size(); 199 int byte_length = str.length() * char_size();
192 int byte_offset = cp_offset * char_size(); 200 int byte_offset = cp_offset * char_size();
193 if (check_end_of_string) { 201 if (check_end_of_string) {
202 // Check that there are at least str.length() characters left in the input.
194 __ cmp(Operand(edi), Immediate(-(byte_offset + byte_length))); 203 __ cmp(Operand(edi), Immediate(-(byte_offset + byte_length)));
195 BranchOrBacktrack(greater, on_failure); 204 BranchOrBacktrack(greater, on_failure);
196 } 205 }
197 206
198 Label backtrack; 207 Label backtrack;
199 if (on_failure == NULL) { 208 if (on_failure == NULL) {
200 // Avoid inlining the Backtrack macro for each test. 209 // Avoid inlining the Backtrack macro for each test.
201 Label skip_backtrack; 210 Label skip_backtrack;
202 __ jmp(&skip_backtrack); 211 __ jmp(&skip_backtrack);
203 __ bind(&backtrack); 212 __ bind(&backtrack);
(...skipping 11 matching lines...) Expand all
215 __ cmpw(Operand(esi, edi, times_1, byte_offset + i * sizeof(uc16)), 224 __ cmpw(Operand(esi, edi, times_1, byte_offset + i * sizeof(uc16)),
216 Immediate(str[i])); 225 Immediate(str[i]));
217 } 226 }
218 BranchOrBacktrack(not_equal, on_failure); 227 BranchOrBacktrack(not_equal, on_failure);
219 } 228 }
220 } 229 }
221 230
222 231
223 void RegExpMacroAssemblerIA32::CheckGreedyLoop(Label* on_equal) { 232 void RegExpMacroAssemblerIA32::CheckGreedyLoop(Label* on_equal) {
224 Label fallthrough; 233 Label fallthrough;
225 __ cmp(edi, Operand(esp, 0)); 234 __ cmp(edi, Operand(backtrack_stackpointer(), 0));
226 __ j(not_equal, &fallthrough); 235 __ j(not_equal, &fallthrough);
227 __ add(Operand(esp), Immediate(4)); // Pop. 236 __ add(Operand(backtrack_stackpointer()), Immediate(kPointerSize)); // Pop.
228 BranchOrBacktrack(no_condition, on_equal); 237 BranchOrBacktrack(no_condition, on_equal);
229 __ bind(&fallthrough); 238 __ bind(&fallthrough);
230 } 239 }
231 240
232 241
233 void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase( 242 void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase(
234 int start_reg, 243 int start_reg,
235 Label* on_no_match) { 244 Label* on_no_match) {
236 Label fallthrough; 245 Label fallthrough;
237 __ mov(edx, register_location(start_reg)); 246 __ mov(edx, register_location(start_reg)); // Index of start of capture
238 __ mov(ecx, register_location(start_reg + 1)); 247 __ mov(ebx, register_location(start_reg + 1)); // Index of end of capture
239 __ sub(ecx, Operand(edx)); // Length to check. 248 __ sub(ebx, Operand(edx)); // Length of capture.
240 BranchOrBacktrack(less, on_no_match); 249
250 // The length of a capture should not be negative. This can only happen
251 // if the end of the capture is unrecorded, or at a point earlier than
252 // the start of the capture.
253 BranchOrBacktrack(less, on_no_match, not_taken);
254
255 // If length is zero, either the capture is empty or it is completely
256 // uncaptured. In either case succeed immediately.
241 __ j(equal, &fallthrough); 257 __ j(equal, &fallthrough);
242 258
243 if (mode_ == ASCII) { 259 if (mode_ == ASCII) {
244 Label success; 260 Label success;
245 Label fail; 261 Label fail;
246 Label loop_increment; 262 Label loop_increment;
263 // Save register contents to make the registers available below.
247 __ push(edi); 264 __ push(edi);
248 __ add(edx, Operand(esi)); 265 __ push(backtrack_stackpointer());
249 __ add(edi, Operand(esi)); 266 // After this, the eax, ebx, ecx, edx and edi registers are available.
250 __ add(ecx, Operand(edi)); 267
268 __ add(edx, Operand(esi)); // Start of capture
269 __ add(edi, Operand(esi)); // Start of text to match against capture.
270 __ add(ebx, Operand(edi)); // End of text to match against capture.
251 271
252 Label loop; 272 Label loop;
253 __ bind(&loop); 273 __ bind(&loop);
254 __ movzx_b(eax, Operand(edi, 0)); 274 __ movzx_b(eax, Operand(edi, 0));
255 __ cmpb_al(Operand(edx, 0)); 275 __ cmpb_al(Operand(edx, 0));
256 __ j(equal, &loop_increment); 276 __ j(equal, &loop_increment);
257 277
258 // Compare lower-case if letters. 278 // Mismatch, try case-insensitive match (converting letters to lower-case).
259 __ or_(eax, 0x20); // To lower-case. 279 __ or_(eax, 0x20); // Convert match character to lower-case.
260 __ lea(ebx, Operand(eax, -'a')); 280 __ lea(ecx, Operand(eax, -'a'));
261 __ cmp(ebx, static_cast<int32_t>('z' - 'a')); 281 __ cmp(ecx, static_cast<int32_t>('z' - 'a')); // Is eax a lowercase letter?
262 __ j(above, &fail); 282 __ j(above, &fail);
263 __ movzx_b(ebx, Operand(edx, 0)); 283 // Also convert capture character.
264 __ or_(ebx, 0x20); // To-lower-case 284 __ movzx_b(ecx, Operand(edx, 0));
265 __ cmp(eax, Operand(ebx)); 285 __ or_(ecx, 0x20);
286
287 __ cmp(eax, Operand(ecx));
266 __ j(not_equal, &fail); 288 __ j(not_equal, &fail);
267 289
268 __ bind(&loop_increment); 290 __ bind(&loop_increment);
291 // Increment pointers into match and capture strings.
269 __ add(Operand(edx), Immediate(1)); 292 __ add(Operand(edx), Immediate(1));
270 __ add(Operand(edi), Immediate(1)); 293 __ add(Operand(edi), Immediate(1));
271 __ cmp(edi, Operand(ecx)); 294 // Compare to end of match, and loop if not done.
295 __ cmp(edi, Operand(ebx));
272 __ j(below, &loop, taken); 296 __ j(below, &loop, taken);
273 __ jmp(&success); 297 __ jmp(&success);
274 298
275 __ bind(&fail); 299 __ bind(&fail);
300 // Restore original values before failing.
301 __ pop(backtrack_stackpointer());
276 __ pop(edi); 302 __ pop(edi);
277 BranchOrBacktrack(no_condition, on_no_match); 303 BranchOrBacktrack(no_condition, on_no_match);
278 304
279 __ bind(&success); 305 __ bind(&success);
280 __ pop(eax); // discard original value of edi 306 // Restore original value before continuing.
307 __ pop(backtrack_stackpointer());
308 // Drop original value of character position.
309 __ add(Operand(esp), Immediate(kPointerSize));
310 // Compute new value of character position after the matched part.
281 __ sub(edi, Operand(esi)); 311 __ sub(edi, Operand(esi));
282 } else { 312 } else {
283 ASSERT(mode_ == UC16); 313 ASSERT(mode_ == UC16);
314 // Save registers before calling C function.
284 __ push(esi); 315 __ push(esi);
285 __ push(edi); 316 __ push(edi);
286 __ push(ecx); 317 __ push(backtrack_stackpointer());
318 __ push(ebx);
287 const int four_arguments = 4; 319 const int four_arguments = 4;
288 FrameAlign(four_arguments); 320 FrameAlign(four_arguments);
289 // Put arguments on stack. 321 // Put arguments into allocated stack area.
290 __ mov(Operand(esp, 3 * kPointerSize), ecx); 322 __ mov(Operand(esp, 3 * kPointerSize), ebx);
291 __ mov(ebx, Operand(ebp, kInputEndOffset)); 323 __ mov(ecx, Operand(ebp, kInputEndOffset));
292 __ add(edi, Operand(ebx)); 324 __ add(edi, Operand(ecx));
293 __ mov(Operand(esp, 2 * kPointerSize), edi); 325 __ mov(Operand(esp, 2 * kPointerSize), edi);
294 __ add(eax, Operand(ebx)); 326 __ add(eax, Operand(ecx));
295 __ mov(Operand(esp, 1 * kPointerSize), eax); 327 __ mov(Operand(esp, 1 * kPointerSize), eax);
296 __ mov(eax, Operand(ebp, kInputBuffer)); 328 __ mov(eax, Operand(ebp, kInputBuffer));
297 __ mov(Operand(esp, 0 * kPointerSize), eax); 329 __ mov(Operand(esp, 0 * kPointerSize), eax);
298 Address function_address = FUNCTION_ADDR(&CaseInsensitiveCompareUC16); 330 Address function_address = FUNCTION_ADDR(&CaseInsensitiveCompareUC16);
299 CallCFunction(function_address, four_arguments); 331 CallCFunction(function_address, four_arguments);
300 __ pop(ecx); 332 // Pop original values before reacting on result value.
333 __ pop(ebx);
334 __ pop(backtrack_stackpointer());
301 __ pop(edi); 335 __ pop(edi);
302 __ pop(esi); 336 __ pop(esi);
303 337
338 // Check if function returned non-zero for success or zero for failure.
304 __ or_(eax, Operand(eax)); 339 __ or_(eax, Operand(eax));
305 BranchOrBacktrack(zero, on_no_match); 340 BranchOrBacktrack(zero, on_no_match);
306 __ add(edi, Operand(ecx)); 341 // On success, increment position by length of capture.
342 __ add(edi, Operand(ebx));
307 } 343 }
308 __ bind(&fallthrough); 344 __ bind(&fallthrough);
309 } 345 }
310 346
311 347
312 void RegExpMacroAssemblerIA32::CheckNotBackReference( 348 void RegExpMacroAssemblerIA32::CheckNotBackReference(
313 int start_reg, 349 int start_reg,
314 Label* on_no_match) { 350 Label* on_no_match) {
315 Label fallthrough; 351 Label fallthrough;
316 Label success; 352 Label success;
317 Label fail; 353 Label fail;
354
355 // Find length of back-referenced capture.
318 __ mov(edx, register_location(start_reg)); 356 __ mov(edx, register_location(start_reg));
319 __ mov(ecx, register_location(start_reg + 1)); 357 __ mov(eax, register_location(start_reg + 1));
320 __ sub(ecx, Operand(edx)); // Length to check. 358 __ sub(eax, Operand(edx)); // Length to check.
359 // Fail on partial or illegal capture (start of capture after end of capture).
321 BranchOrBacktrack(less, on_no_match); 360 BranchOrBacktrack(less, on_no_match);
361 // Succeed on empty capture (including no capture)
322 __ j(equal, &fallthrough); 362 __ j(equal, &fallthrough);
363
323 // Check that there are sufficient characters left in the input. 364 // Check that there are sufficient characters left in the input.
324
325 __ mov(ebx, edi); 365 __ mov(ebx, edi);
326 __ add(ebx, Operand(ecx)); 366 __ add(ebx, Operand(eax));
327 BranchOrBacktrack(greater, on_no_match); 367 BranchOrBacktrack(greater, on_no_match);
328 368
329 __ mov(ebx, edi); 369 // Save register to make it available below.
330 __ add(edi, Operand(esi)); 370 __ push(backtrack_stackpointer());
331 __ add(edx, Operand(esi)); 371
332 __ add(ecx, Operand(edi)); 372 // Compute pointers to match string and capture string
373 __ lea(ebx, Operand(esi, edi, times_1, 0)); // Start of match.
374 __ add(edx, Operand(esi)); // Start of capture.
375 __ lea(ecx, Operand(eax, ebx, times_1, 0)); // End of match
333 376
334 Label loop; 377 Label loop;
335 __ bind(&loop); 378 __ bind(&loop);
336 if (mode_ == ASCII) { 379 if (mode_ == ASCII) {
337 __ movzx_b(eax, Operand(edx, 0)); 380 __ movzx_b(eax, Operand(edx, 0));
338 __ cmpb_al(Operand(edi, 0)); 381 __ cmpb_al(Operand(ebx, 0));
339 } else { 382 } else {
340 ASSERT(mode_ == UC16); 383 ASSERT(mode_ == UC16);
341 __ movzx_w(eax, Operand(edx, 0)); 384 __ movzx_w(eax, Operand(edx, 0));
342 __ cmpw_ax(Operand(edi, 0)); 385 __ cmpw_ax(Operand(ebx, 0));
343 } 386 }
344 __ j(not_equal, &fail); 387 __ j(not_equal, &fail);
388 // Increment pointers into capture and match string.
345 __ add(Operand(edx), Immediate(char_size())); 389 __ add(Operand(edx), Immediate(char_size()));
346 __ add(Operand(edi), Immediate(char_size())); 390 __ add(Operand(ebx), Immediate(char_size()));
347 __ cmp(edi, Operand(ecx)); 391 // Check if we have reached end of match area.
392 __ cmp(ebx, Operand(ecx));
348 __ j(below, &loop); 393 __ j(below, &loop);
349 __ jmp(&success); 394 __ jmp(&success);
350 395
351 __ bind(&fail); 396 __ bind(&fail);
352 __ mov(edi, ebx); 397 // Restore backtrack stackpointer.
398 __ pop(backtrack_stackpointer());
353 BranchOrBacktrack(no_condition, on_no_match); 399 BranchOrBacktrack(no_condition, on_no_match);
354 400
355 __ bind(&success); 401 __ bind(&success);
356 __ sub(edi, Operand(esi)); 402 // Move current character position to position after match.
403 __ mov(edi, ecx);
404 __ sub(Operand(edi), esi);
405 // Restore backtrack stackpointer.
406 __ pop(backtrack_stackpointer());
407
357 __ bind(&fallthrough); 408 __ bind(&fallthrough);
358 } 409 }
359 410
360 411
361 void RegExpMacroAssemblerIA32::CheckNotRegistersEqual(int reg1, 412 void RegExpMacroAssemblerIA32::CheckNotRegistersEqual(int reg1,
362 int reg2, 413 int reg2,
363 Label* on_not_equal) { 414 Label* on_not_equal) {
364 __ mov(eax, register_location(reg1)); 415 __ mov(eax, register_location(reg1));
365 __ cmp(eax, register_location(reg2)); 416 __ cmp(eax, register_location(reg2));
366 BranchOrBacktrack(not_equal, on_not_equal); 417 BranchOrBacktrack(not_equal, on_not_equal);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 uc16 minus, 450 uc16 minus,
400 uc16 mask, 451 uc16 mask,
401 Label* on_not_equal) { 452 Label* on_not_equal) {
402 ASSERT(minus < String::kMaxUC16CharCode); 453 ASSERT(minus < String::kMaxUC16CharCode);
403 __ lea(eax, Operand(current_character(), -minus)); 454 __ lea(eax, Operand(current_character(), -minus));
404 __ and_(eax, mask); 455 __ and_(eax, mask);
405 __ cmp(eax, c); 456 __ cmp(eax, c);
406 BranchOrBacktrack(not_equal, on_not_equal); 457 BranchOrBacktrack(not_equal, on_not_equal);
407 } 458 }
408 459
460
409 bool RegExpMacroAssemblerIA32::CheckSpecialCharacterClass(uc16 type, 461 bool RegExpMacroAssemblerIA32::CheckSpecialCharacterClass(uc16 type,
410 int cp_offset, 462 int cp_offset,
411 bool check_offset, 463 bool check_offset,
412 Label* on_no_match) { 464 Label* on_no_match) {
413 // Range checks (c in min..max) are generally implemented by an unsigned 465 // Range checks (c in min..max) are generally implemented by an unsigned
414 // (c - min) <= (max - min) check 466 // (c - min) <= (max - min) check
415 switch (type) { 467 switch (type) {
416 case 's': 468 case 's':
417 // Match space-characters 469 // Match space-characters
418 if (mode_ == ASCII) { 470 if (mode_ == ASCII) {
419 // ASCII space characters are '\t'..'\r' and ' '. 471 // ASCII space characters are '\t'..'\r' and ' '.
420 if (check_offset) { 472 if (check_offset) {
421 LoadCurrentCharacter(cp_offset, on_no_match); 473 LoadCurrentCharacter(cp_offset, on_no_match);
422 } else { 474 } else {
423 LoadCurrentCharacterUnchecked(cp_offset, 1); 475 LoadCurrentCharacterUnchecked(cp_offset, 1);
424 } 476 }
425 Label success; 477 Label success;
426 __ cmp(current_character(), ' '); 478 __ cmp(current_character(), ' ');
427 __ j(equal, &success); 479 __ j(equal, &success);
428 // Check range 0x09..0x0d 480 // Check range 0x09..0x0d
429 __ sub(Operand(current_character()), Immediate('\t')); 481 __ sub(Operand(current_character()), Immediate('\t'));
430 __ cmp(current_character(), '\r' - '\t'); 482 __ cmp(current_character(), '\r' - '\t');
431 BranchOrBacktrack(above_equal, on_no_match); 483 BranchOrBacktrack(above, on_no_match);
432 __ bind(&success); 484 __ bind(&success);
433 return true; 485 return true;
434 } 486 }
435 return false; 487 return false;
436 case 'S': 488 case 'S':
437 // Match non-space characters. 489 // Match non-space characters.
438 if (check_offset) { 490 if (check_offset) {
439 LoadCurrentCharacter(cp_offset, on_no_match, 1); 491 LoadCurrentCharacter(cp_offset, on_no_match, 1);
440 } else { 492 } else {
441 LoadCurrentCharacterUnchecked(cp_offset, 1); 493 LoadCurrentCharacterUnchecked(cp_offset, 1);
442 } 494 }
443 if (mode_ == ASCII) { 495 if (mode_ == ASCII) {
444 // ASCII space characters are '\t'..'\r' and ' '. 496 // ASCII space characters are '\t'..'\r' and ' '.
445 __ cmp(current_character(), ' '); 497 __ cmp(current_character(), ' ');
446 BranchOrBacktrack(equal, on_no_match); 498 BranchOrBacktrack(equal, on_no_match);
447 __ sub(Operand(current_character()), Immediate('\t')); 499 __ sub(Operand(current_character()), Immediate('\t'));
448 __ cmp(current_character(), '\r' - '\t'); 500 __ cmp(current_character(), '\r' - '\t');
449 BranchOrBacktrack(below, on_no_match); 501 BranchOrBacktrack(below_equal, on_no_match);
450 return true; 502 return true;
451 } 503 }
452 return false; 504 return false;
453 case 'd': 505 case 'd':
454 // Match ASCII digits ('0'..'9') 506 // Match ASCII digits ('0'..'9')
455 if (check_offset) { 507 if (check_offset) {
456 LoadCurrentCharacter(cp_offset, on_no_match, 1); 508 LoadCurrentCharacter(cp_offset, on_no_match, 1);
457 } else { 509 } else {
458 LoadCurrentCharacterUnchecked(cp_offset, 1); 510 LoadCurrentCharacterUnchecked(cp_offset, 1);
459 } 511 }
460 __ sub(Operand(current_character()), Immediate('0')); 512 __ sub(Operand(current_character()), Immediate('0'));
461 __ cmp(current_character(), '9' - '0'); 513 __ cmp(current_character(), '9' - '0');
462 BranchOrBacktrack(greater_equal, on_no_match); 514 BranchOrBacktrack(above, on_no_match);
463 return true; 515 return true;
464 case 'D': 516 case 'D':
465 // Match non ASCII-digits 517 // Match non ASCII-digits
466 if (check_offset) { 518 if (check_offset) {
467 LoadCurrentCharacter(cp_offset, on_no_match, 1); 519 LoadCurrentCharacter(cp_offset, on_no_match, 1);
468 } else { 520 } else {
469 LoadCurrentCharacterUnchecked(cp_offset, 1); 521 LoadCurrentCharacterUnchecked(cp_offset, 1);
470 } 522 }
471 __ sub(Operand(current_character()), Immediate('0')); 523 __ sub(Operand(current_character()), Immediate('0'));
472 __ cmp(current_character(), '9' - '0'); 524 __ cmp(current_character(), '9' - '0');
473 BranchOrBacktrack(below, on_no_match); 525 BranchOrBacktrack(below_equal, on_no_match);
474 return true; 526 return true;
475 case '.': { 527 case '.': {
476 // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029) 528 // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029)
477 if (check_offset) { 529 if (check_offset) {
478 LoadCurrentCharacter(cp_offset, on_no_match, 1); 530 LoadCurrentCharacter(cp_offset, on_no_match, 1);
479 } else { 531 } else {
480 LoadCurrentCharacterUnchecked(cp_offset, 1); 532 LoadCurrentCharacterUnchecked(cp_offset, 1);
481 } 533 }
482 // Compute hash value so exactly 0x0a and 0x0d become zero. 534 __ xor_(Operand(current_character()), Immediate(0x01));
483 __ sub(Operand(current_character()), Immediate('\n')); 535 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c
484 __ mov(eax, current_character()); 536 __ sub(Operand(current_character()), Immediate(0x0b));
485 __ and_(current_character(), 0x01); 537 __ cmp(current_character(), 0x0c - 0x0b);
486 __ shr(eax, 1); 538 BranchOrBacktrack(below_equal, on_no_match);
487 __ xor_(current_character(), Operand(eax));
488 BranchOrBacktrack(equal, on_no_match);
489 if (mode_ == UC16) { 539 if (mode_ == UC16) {
490 // Compare original value to 0x2028 and 0x2029, using the already 540 // Compare original value to 0x2028 and 0x2029, using the already
491 // computed ((current_char - '\n') >> 1) in eax. 541 // computed (current_char ^ 0x01 - 0x0b). I.e., check for
492 __ cmp(eax, (0x2028 - '\n') >> 1); 542 // 0x201d (0x2028 - 0x0b) or 0x201e.
493 BranchOrBacktrack(equal, on_no_match); 543 __ sub(Operand(current_character()), Immediate(0x2028 - 0x0b));
544 __ cmp(current_character(), 1);
545 BranchOrBacktrack(below_equal, on_no_match);
494 } 546 }
495 return true; 547 return true;
496 } 548 }
497 case '*': 549 case '*':
498 // Match any character. 550 // Match any character.
499 if (check_offset) { 551 if (check_offset) {
500 CheckPosition(cp_offset, on_no_match); 552 CheckPosition(cp_offset, on_no_match);
501 } 553 }
502 return true; 554 return true;
503 // No custom implementation (yet): w, W, s(UC16), S(UC16). 555 // No custom implementation (yet): w, W, s(UC16), S(UC16).
504 default: 556 default:
505 return false; 557 return false;
506 } 558 }
507 } 559 }
508 560
509 void RegExpMacroAssemblerIA32::DispatchHalfNibbleMap( 561 void RegExpMacroAssemblerIA32::DispatchHalfNibbleMap(
510 uc16 start, 562 uc16 start,
511 Label* half_nibble_map, 563 Label* half_nibble_map,
512 const Vector<Label*>& destinations) { 564 const Vector<Label*>& destinations) {
513 UNIMPLEMENTED(); 565 UNIMPLEMENTED();
514 __ mov(eax, current_character());
515 __ sub(Operand(eax), Immediate(start));
516
517 __ mov(ecx, eax);
518 __ shr(eax, 2);
519 // FIXME: ecx must hold address of map
520 __ movzx_b(eax, Operand(ecx, eax, times_1, 0));
521 __ and_(ecx, 0x03);
522 __ add(ecx, Operand(ecx));
523 __ shr(eax); // Shift right cl times
524
525 Label second_bit_set, case_3, case_1;
526 __ test(eax, Immediate(0x02));
527 __ j(not_zero, &second_bit_set);
528 __ test(eax, Immediate(0x01));
529 __ j(not_zero, &case_1);
530 // Case 0:
531 __ jmp(destinations[0]);
532 __ bind(&case_1);
533 // Case 1:
534 __ jmp(destinations[1]);
535 __ bind(&second_bit_set);
536 __ test(eax, Immediate(0x01));
537 __ j(not_zero, &case_3);
538 // Case 2
539 __ jmp(destinations[2]);
540 __ bind(&case_3);
541 // Case 3:
542 __ jmp(destinations[3]);
543 } 566 }
544 567
545 568
546 void RegExpMacroAssemblerIA32::DispatchByteMap( 569 void RegExpMacroAssemblerIA32::DispatchByteMap(
547 uc16 start, 570 uc16 start,
548 Label* byte_map, 571 Label* byte_map,
549 const Vector<Label*>& destinations) { 572 const Vector<Label*>& destinations) {
550 UNIMPLEMENTED(); 573 UNIMPLEMENTED();
551
552 Label fallthrough;
553 __ mov(eax, current_character());
554 __ sub(Operand(eax), Immediate(start));
555 __ cmp(eax, 64); // FIXME: 64 = size of map. Found somehow??
556 __ j(greater_equal, &fallthrough);
557 // TODO(lrn): ecx must hold address of map
558 __ movzx_b(eax, Operand(ecx, eax, times_1, 0));
559 // jump table: jump to destinations[eax];
560
561 __ bind(&fallthrough);
562 } 574 }
563 575
564 576
565 void RegExpMacroAssemblerIA32::DispatchHighByteMap( 577 void RegExpMacroAssemblerIA32::DispatchHighByteMap(
566 byte start, 578 byte start,
567 Label* byte_map, 579 Label* byte_map,
568 const Vector<Label*>& destinations) { 580 const Vector<Label*>& destinations) {
569 UNIMPLEMENTED(); 581 UNIMPLEMENTED();
570
571 Label fallthrough;
572 __ mov(eax, current_character());
573 __ shr(eax, 8);
574 __ sub(Operand(eax), Immediate(start));
575 __ cmp(eax, destinations.length() - start);
576 __ j(greater_equal, &fallthrough);
577
578 // TODO(lrn) jumptable: jump to destinations[eax]
579 __ bind(&fallthrough);
580 } 582 }
581 583
582 584
583 void RegExpMacroAssemblerIA32::EmitOrLink(Label* label) { 585 void RegExpMacroAssemblerIA32::EmitOrLink(Label* label) {
584 UNIMPLEMENTED(); // Has no use. 586 UNIMPLEMENTED(); // Has no use.
585 } 587 }
586 588
587 589
588 void RegExpMacroAssemblerIA32::Fail() { 590 void RegExpMacroAssemblerIA32::Fail() {
591 ASSERT(FAILURE == 0); // Return value for failure is zero.
589 __ xor_(eax, Operand(eax)); // zero eax. 592 __ xor_(eax, Operand(eax)); // zero eax.
590 __ jmp(&exit_label_); 593 __ jmp(&exit_label_);
591 } 594 }
592 595
593 596
594 Handle<Object> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) { 597 Handle<Object> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
595 // 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
596 // registers we need. 599 // registers we need.
597 600
598 // Entry code: 601 // Entry code:
599 __ bind(&entry_label_); 602 __ bind(&entry_label_);
603 // Start new stack frame.
604 __ push(ebp);
605 __ mov(ebp, esp);
600 // Save callee-save registers. Order here should correspond to order of 606 // Save callee-save registers. Order here should correspond to order of
601 // kBackup_ebx etc. 607 // kBackup_ebx etc.
602 __ push(esi); 608 __ push(esi);
603 __ push(edi); 609 __ push(edi);
604 __ push(ebx); // Callee-save on MacOS. 610 __ push(ebx); // Callee-save on MacOS.
605 __ enter(Immediate(num_registers_ * kPointerSize)); 611 __ push(Immediate(0)); // Make room for input start minus one
612
613 // Check if we have space on the stack for registers.
614 Label retry_stack_check;
615 Label stack_limit_hit;
616 Label stack_ok;
617
618 __ bind(&retry_stack_check);
619 ExternalReference stack_guard_limit =
620 ExternalReference::address_of_stack_guard_limit();
621 __ mov(ecx, esp);
622 __ sub(ecx, Operand::StaticVariable(stack_guard_limit));
623 // Handle it if the stack pointer is already below the stack limit.
624 __ j(below_equal, &stack_limit_hit, not_taken);
625 // Check if there is room for the variable number of registers above
626 // the stack limit.
627 __ cmp(ecx, num_registers_ * kPointerSize);
628 __ j(above_equal, &stack_ok, taken);
629 // Exit with exception.
630 __ mov(eax, EXCEPTION);
631 __ jmp(&exit_label_);
632
633 __ bind(&stack_limit_hit);
634 int num_arguments = 2;
635 FrameAlign(num_arguments);
636 __ mov(Operand(esp, 1 * kPointerSize), Immediate(self_));
637 __ lea(eax, Operand(esp, -kPointerSize));
638 __ mov(Operand(esp, 0 * kPointerSize), eax);
639 CallCFunction(FUNCTION_ADDR(&CheckStackGuardState), num_arguments);
640 __ or_(eax, Operand(eax));
641 // If returned value is non-zero, the stack guard reports the actual
642 // stack limit being hit and an exception has already been raised.
643 // Otherwise it was a preemption and we just check the limit again.
644 __ j(equal, &retry_stack_check);
645 // Return value was non-zero. Exit with exception.
646 __ mov(eax, EXCEPTION);
647 __ jmp(&exit_label_);
648
649 __ bind(&stack_ok);
650
651 // Allocate space on stack for registers.
652 __ sub(Operand(esp), Immediate(num_registers_ * kPointerSize));
606 // Load string length. 653 // Load string length.
607 __ mov(esi, Operand(ebp, kInputEndOffset)); 654 __ mov(esi, Operand(ebp, kInputEndOffset));
608 // Load input position. 655 // Load input position.
609 __ mov(edi, Operand(ebp, kInputStartOffset)); 656 __ mov(edi, Operand(ebp, kInputStartOffset));
610 // Set up edi to be negative offset from string end. 657 // Set up edi to be negative offset from string end.
611 __ sub(edi, Operand(esi)); 658 __ sub(edi, Operand(esi));
612 // Set up esi to be end of string. First get location. 659 // Set up esi to be end of string. First get location.
613 __ mov(edx, Operand(ebp, kInputBuffer)); 660 __ mov(edx, Operand(ebp, kInputBuffer));
614 // Dereference location to get string start. 661 // Dereference location to get string start.
615 __ mov(edx, Operand(edx, 0)); 662 __ mov(edx, Operand(edx, 0));
616 // Add start to length to complete esi setup. 663 // Add start to length to complete esi setup.
617 __ add(esi, Operand(edx)); 664 __ add(esi, Operand(edx));
618 if (num_saved_registers_ > 0) { 665 if (num_saved_registers_ > 0) {
619 // Fill saved registers with initial value = start offset - 1 666 // Fill saved registers with initial value = start offset - 1
620 __ mov(ecx, -num_saved_registers_); 667 // Fill in stack push order, to avoid accessing across an unwritten
621 __ mov(eax, Operand(edi)); 668 // page (a problem on Windows).
622 __ sub(Operand(eax), Immediate(char_size())); 669 __ mov(ecx, kRegisterZero);
670 // Set eax to address of char before start of input
671 // (effectively string position -1).
672 __ lea(eax, Operand(edi, -char_size()));
673 // Store this value in a local variable, for use when clearing
674 // position registers.
675 __ mov(Operand(ebp, kInputStartMinusOne), eax);
623 Label init_loop; 676 Label init_loop;
624 __ bind(&init_loop); 677 __ bind(&init_loop);
625 __ mov(Operand(ebp, ecx, times_4, +0), eax); 678 __ mov(Operand(ebp, ecx, times_1, +0), eax);
626 __ inc(ecx); 679 __ sub(Operand(ecx), Immediate(kPointerSize));
627 __ j(not_equal, &init_loop); 680 __ cmp(ecx, kRegisterZero - num_saved_registers_ * kPointerSize);
681 __ j(greater, &init_loop);
628 } 682 }
683 // Ensure that we have written to each stack page, in order. Skipping a page
684 // on Windows can cause segmentation faults. Assuming page size is 4k.
685 const int kPageSize = 4096;
686 const int kRegistersPerPage = kPageSize / kPointerSize;
687 for (int i = num_saved_registers_ + kRegistersPerPage - 1;
688 i < num_registers_;
689 i += kRegistersPerPage) {
690 __ mov(register_location(i), eax); // One write every page.
691 }
692
693
694 // Initialize backtrack stack pointer.
695 __ mov(backtrack_stackpointer(), Operand(ebp, kStackHighEnd));
629 // Load previous char as initial value of current-character. 696 // Load previous char as initial value of current-character.
630 Label at_start; 697 Label at_start;
631 __ cmp(Operand(ebp, kAtStart), Immediate(0)); 698 __ cmp(Operand(ebp, kAtStart), Immediate(0));
632 __ j(not_equal, &at_start); 699 __ j(not_equal, &at_start);
633 LoadCurrentCharacterUnchecked(-1, 1); // Load previous char. 700 LoadCurrentCharacterUnchecked(-1, 1); // Load previous char.
634 __ jmp(&start_label_); 701 __ jmp(&start_label_);
635 __ bind(&at_start); 702 __ bind(&at_start);
636 __ mov(current_character(), '\n'); 703 __ mov(current_character(), '\n');
637 __ jmp(&start_label_); 704 __ jmp(&start_label_);
638 705
639 706
640 // Exit code: 707 // Exit code:
641 if (success_label_.is_linked()) { 708 if (success_label_.is_linked()) {
642 // Success 709 // Save captures when successful.
643 __ bind(&success_label_); 710 __ bind(&success_label_);
644 if (num_saved_registers_ > 0) { 711 if (num_saved_registers_ > 0) {
645 // copy captures to output 712 // copy captures to output
646 __ mov(ebx, Operand(ebp, kRegisterOutput)); 713 __ mov(ebx, Operand(ebp, kRegisterOutput));
647 __ mov(ecx, Operand(ebp, kInputEndOffset)); 714 __ mov(ecx, Operand(ebp, kInputEndOffset));
648 __ sub(ecx, Operand(ebp, kInputStartOffset)); 715 __ sub(ecx, Operand(ebp, kInputStartOffset));
649 for (int i = 0; i < num_saved_registers_; i++) { 716 for (int i = 0; i < num_saved_registers_; i++) {
650 __ mov(eax, register_location(i)); 717 __ mov(eax, register_location(i));
651 __ add(eax, Operand(ecx)); // Convert to index from start, not end. 718 __ add(eax, Operand(ecx)); // Convert to index from start, not end.
652 if (mode_ == UC16) { 719 if (mode_ == UC16) {
653 __ sar(eax, 1); // Convert byte index to character index. 720 __ sar(eax, 1); // Convert byte index to character index.
654 } 721 }
655 __ mov(Operand(ebx, i * kPointerSize), eax); 722 __ mov(Operand(ebx, i * kPointerSize), eax);
656 } 723 }
657 } 724 }
658 __ mov(eax, Immediate(1)); 725 __ mov(eax, Immediate(SUCCESS));
659 } 726 }
660 // Exit and return eax 727 // Exit and return eax
661 __ bind(&exit_label_); 728 __ bind(&exit_label_);
662 __ leave(); 729 // Skip esp past regexp registers.
730 __ lea(esp, Operand(ebp, kBackup_ebx));
731 // Restore callee-save registers.
663 __ pop(ebx); 732 __ pop(ebx);
664 __ pop(edi); 733 __ pop(edi);
665 __ pop(esi); 734 __ pop(esi);
735 // Exit function frame, restore previus one.
736 __ pop(ebp);
666 __ ret(0); 737 __ ret(0);
667 738
668 // Backtrack code (branch target for conditional backtracks). 739 // Backtrack code (branch target for conditional backtracks).
669 if (backtrack_label_.is_linked()) { 740 if (backtrack_label_.is_linked()) {
670 __ bind(&backtrack_label_); 741 __ bind(&backtrack_label_);
671 Backtrack(); 742 Backtrack();
672 } 743 }
673 744
745 Label exit_with_exception;
746
674 // Preempt-code 747 // Preempt-code
675 if (check_preempt_label_.is_linked()) { 748 if (check_preempt_label_.is_linked()) {
676 __ bind(&check_preempt_label_); 749 __ bind(&check_preempt_label_);
677 // TODO(lrn): call C function to check the stack guard and return current 750
678 // stack state (0 = ok, positive = out of stack, negative = preempt). 751 __ push(backtrack_stackpointer());
679 // Then dispatch to an action depending on state, and loop.
680 __ push(edi); 752 __ push(edi);
681 753
682 Label retry; 754 Label retry;
683 Label stack_overflow;
684 755
685 __ bind(&retry); 756 __ bind(&retry);
686 int num_arguments = 2; 757 int num_arguments = 2;
687 FrameAlign(num_arguments); 758 FrameAlign(num_arguments);
688 __ mov(Operand(esp, 1 * kPointerSize), Immediate(self_)); 759 __ mov(Operand(esp, 1 * kPointerSize), Immediate(self_));
689 __ lea(eax, Operand(esp, -kPointerSize)); 760 __ lea(eax, Operand(esp, -kPointerSize));
690 __ mov(Operand(esp, 0 * kPointerSize), eax); 761 __ mov(Operand(esp, 0 * kPointerSize), eax);
691 CallCFunction(FUNCTION_ADDR(&CheckStackGuardState), num_arguments); 762 CallCFunction(FUNCTION_ADDR(&CheckStackGuardState), num_arguments);
763 // Return value must be zero. We cannot have a stack overflow at
764 // this point, since we checked the stack on entry and haven't
765 // pushed anything since, that we haven't also popped again.
692 766
693 ExternalReference stack_guard_limit = 767 ExternalReference stack_guard_limit =
694 ExternalReference::address_of_stack_guard_limit(); 768 ExternalReference::address_of_stack_guard_limit();
695 769 // Check if we are still preempted.
696 __ or_(eax, Operand(eax));
697 __ j(not_equal, &stack_overflow);
698
699 __ cmp(esp, Operand::StaticVariable(stack_guard_limit)); 770 __ cmp(esp, Operand::StaticVariable(stack_guard_limit));
700 __ j(below_equal, &retry); 771 __ j(below_equal, &retry);
701 772
702 __ pop(edi); 773 __ pop(edi);
774 __ pop(backtrack_stackpointer());
703 // String might have moved: Recompute esi from scratch. 775 // String might have moved: Recompute esi from scratch.
704 __ mov(esi, Operand(esp, kInputBuffer)); 776 __ mov(esi, Operand(ebp, kInputBuffer));
705 __ mov(esi, Operand(esi, 0)); 777 __ mov(esi, Operand(esi, 0));
706 __ add(esi, Operand(esp, kInputEndOffset)); 778 __ add(esi, Operand(ebp, kInputEndOffset));
707 SafeReturn(); 779 SafeReturn();
780 }
708 781
709 __ bind(&stack_overflow); 782 // Backtrack stack overflow code.
710 // Exit with result -1 to signal thrown exception. 783 if (stack_overflow_label_.is_linked()) {
711 __ mov(eax, -1); 784 __ bind(&stack_overflow_label_);
785 // Reached if the backtrack-stack limit has been hit.
786
787 Label grow_failed;
788 // Save registers before calling C function
789 __ push(esi);
790 __ push(edi);
791
792 // Call GrowStack(backtrack_stackpointer())
793 int num_arguments = 1;
794 FrameAlign(num_arguments);
795 __ mov(Operand(esp, 0), backtrack_stackpointer());
796 CallCFunction(FUNCTION_ADDR(&GrowStack), num_arguments);
797 // If return NULL, we have failed to grow the stack, and
798 // must exit with a stack-overflow exception.
799 __ or_(eax, Operand(eax));
800 __ j(equal, &exit_with_exception);
801 // Otherwise use return value as new stack pointer.
802 __ mov(backtrack_stackpointer(), eax);
803 // Restore saved registers and continue.
804 __ pop(edi);
805 __ pop(esi);
806 SafeReturn();
807 }
808
809 if (exit_with_exception.is_linked()) {
810 // If any of the code above needed to exit with an exception.
811 __ bind(&exit_with_exception);
812 // Exit with Result EXCEPTION(-1) to signal thrown exception.
813 __ mov(eax, EXCEPTION);
712 __ jmp(&exit_label_); 814 __ jmp(&exit_label_);
713 } 815 }
714 816
715 CodeDesc code_desc; 817 CodeDesc code_desc;
716 masm_->GetCode(&code_desc); 818 masm_->GetCode(&code_desc);
717 Handle<Code> code = Factory::NewCode(code_desc, 819 Handle<Code> code = Factory::NewCode(code_desc,
718 NULL, 820 NULL,
719 Code::ComputeFlags(Code::REGEXP), 821 Code::ComputeFlags(Code::REGEXP),
720 self_); 822 self_);
721 LOG(CodeCreateEvent("RegExp", *code, *(source->ToCString()))); 823 LOG(CodeCreateEvent("RegExp", *code, *(source->ToCString())));
(...skipping 15 matching lines...) Expand all
737 839
738 840
739 void RegExpMacroAssemblerIA32::IfRegisterLT(int reg, 841 void RegExpMacroAssemblerIA32::IfRegisterLT(int reg,
740 int comparand, 842 int comparand,
741 Label* if_lt) { 843 Label* if_lt) {
742 __ cmp(register_location(reg), Immediate(comparand)); 844 __ cmp(register_location(reg), Immediate(comparand));
743 BranchOrBacktrack(less, if_lt); 845 BranchOrBacktrack(less, if_lt);
744 } 846 }
745 847
746 848
849 void RegExpMacroAssemblerIA32::IfRegisterEqPos(int reg,
850 Label* if_eq) {
851 __ cmp(edi, register_location(reg));
852 BranchOrBacktrack(equal, if_eq);
853 }
854
855
747 RegExpMacroAssembler::IrregexpImplementation 856 RegExpMacroAssembler::IrregexpImplementation
748 RegExpMacroAssemblerIA32::Implementation() { 857 RegExpMacroAssemblerIA32::Implementation() {
749 return kIA32Implementation; 858 return kIA32Implementation;
750 } 859 }
751 860
752 861
753 void RegExpMacroAssemblerIA32::LoadCurrentCharacter(int cp_offset, 862 void RegExpMacroAssemblerIA32::LoadCurrentCharacter(int cp_offset,
754 Label* on_end_of_input, 863 Label* on_end_of_input,
755 bool check_bounds, 864 bool check_bounds,
756 int characters) { 865 int characters) {
757 ASSERT(cp_offset >= 0); 866 ASSERT(cp_offset >= 0);
758 ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works) 867 ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works)
759 CheckPosition(cp_offset + characters - 1, on_end_of_input); 868 CheckPosition(cp_offset + characters - 1, on_end_of_input);
760 LoadCurrentCharacterUnchecked(cp_offset, characters); 869 LoadCurrentCharacterUnchecked(cp_offset, characters);
761 } 870 }
762 871
763 872
764 void RegExpMacroAssemblerIA32::PopCurrentPosition() { 873 void RegExpMacroAssemblerIA32::PopCurrentPosition() {
765 __ pop(edi); 874 Pop(edi);
766 } 875 }
767 876
768 877
769 void RegExpMacroAssemblerIA32::PopRegister(int register_index) { 878 void RegExpMacroAssemblerIA32::PopRegister(int register_index) {
770 __ pop(register_location(register_index)); 879 Pop(eax);
880 __ mov(register_location(register_index), eax);
771 } 881 }
772 882
773 883
774 void RegExpMacroAssemblerIA32::PushBacktrack(Label* label) { 884 void RegExpMacroAssemblerIA32::PushBacktrack(Label* label) {
775 __ push(Immediate::CodeRelativeOffset(label)); 885 Push(Immediate::CodeRelativeOffset(label));
776 CheckStackLimit(); 886 CheckStackLimit();
777 } 887 }
778 888
779 889
780 void RegExpMacroAssemblerIA32::PushCurrentPosition() { 890 void RegExpMacroAssemblerIA32::PushCurrentPosition() {
781 __ push(edi); 891 Push(edi);
782 } 892 }
783 893
784 894
785 void RegExpMacroAssemblerIA32::PushRegister(int register_index) { 895 void RegExpMacroAssemblerIA32::PushRegister(int register_index,
786 __ push(register_location(register_index)); 896 StackCheckFlag check_stack_limit) {
897 __ mov(eax, register_location(register_index));
898 Push(eax);
899 if (check_stack_limit) CheckStackLimit();
787 } 900 }
788 901
789 902
790 void RegExpMacroAssemblerIA32::ReadCurrentPositionFromRegister(int reg) { 903 void RegExpMacroAssemblerIA32::ReadCurrentPositionFromRegister(int reg) {
791 __ mov(edi, register_location(reg)); 904 __ mov(edi, register_location(reg));
792 } 905 }
793 906
794 907
795 void RegExpMacroAssemblerIA32::ReadStackPointerFromRegister(int reg) { 908 void RegExpMacroAssemblerIA32::ReadStackPointerFromRegister(int reg) {
796 __ mov(esp, register_location(reg)); 909 __ mov(backtrack_stackpointer(), register_location(reg));
797 } 910 }
798 911
799 912
800 void RegExpMacroAssemblerIA32::SetRegister(int register_index, int to) { 913 void RegExpMacroAssemblerIA32::SetRegister(int register_index, int to) {
801 ASSERT(register_index >= num_saved_registers_); // Reserved for positions! 914 ASSERT(register_index >= num_saved_registers_); // Reserved for positions!
802 __ mov(register_location(register_index), Immediate(to)); 915 __ mov(register_location(register_index), Immediate(to));
803 } 916 }
804 917
805 918
806 void RegExpMacroAssemblerIA32::Succeed() { 919 void RegExpMacroAssemblerIA32::Succeed() {
807 __ jmp(&success_label_); 920 __ jmp(&success_label_);
808 } 921 }
809 922
810 923
811 void RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister(int reg, 924 void RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister(int reg,
812 int cp_offset) { 925 int cp_offset) {
813 if (cp_offset == 0) { 926 if (cp_offset == 0) {
814 __ mov(register_location(reg), edi); 927 __ mov(register_location(reg), edi);
815 } else { 928 } else {
816 __ lea(eax, Operand(edi, cp_offset * char_size())); 929 __ lea(eax, Operand(edi, cp_offset * char_size()));
817 __ mov(register_location(reg), eax); 930 __ mov(register_location(reg), eax);
818 } 931 }
819 } 932 }
820 933
821 934
935 void RegExpMacroAssemblerIA32::ClearRegister(int reg) {
936 __ mov(eax, Operand(ebp, kInputStartMinusOne));
937 __ mov(register_location(reg), eax);
938 }
939
940
822 void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) { 941 void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) {
823 __ mov(register_location(reg), esp); 942 __ mov(register_location(reg), backtrack_stackpointer());
824 } 943 }
825 944
826 945
827 // Private methods: 946 // Private methods:
828 947
829 948
830 static unibrow::Mapping<unibrow::Ecma262Canonicalize> canonicalize; 949 static unibrow::Mapping<unibrow::Ecma262Canonicalize> canonicalize;
831 950
832 951
952 RegExpMacroAssemblerIA32::Result RegExpMacroAssemblerIA32::Execute(
953 Code* code,
954 Address* input,
955 int start_offset,
956 int end_offset,
957 int* output,
958 bool at_start) {
959 typedef int (*matcher)(Address*, int, int, int*, int, void*);
960 matcher matcher_func = FUNCTION_CAST<matcher>(code->entry());
961
962 int at_start_val = at_start ? 1 : 0;
963
964 // Ensure that the minimum stack has been allocated.
965 RegExpStack stack;
966 void* stack_top = RegExpStack::stack_top();
967
968 int result = matcher_func(input,
969 start_offset,
970 end_offset,
971 output,
972 at_start_val,
973 stack_top);
974
975 if (result < 0 && !Top::has_pending_exception()) {
976 // We detected a stack overflow in RegExp code, but haven't created
977 // the exception yet.
978 Top::StackOverflow();
979 }
980 return (result < 0) ? EXCEPTION : (result ? SUCCESS : FAILURE);
981 }
982
983
833 int RegExpMacroAssemblerIA32::CaseInsensitiveCompareUC16(uc16** buffer, 984 int RegExpMacroAssemblerIA32::CaseInsensitiveCompareUC16(uc16** buffer,
834 int byte_offset1, 985 int byte_offset1,
835 int byte_offset2, 986 int byte_offset2,
836 size_t byte_length) { 987 size_t byte_length) {
837 // This function is not allowed to cause a garbage collection. 988 // This function is not allowed to cause a garbage collection.
838 // A GC might move the calling generated code and invalidate the 989 // A GC might move the calling generated code and invalidate the
839 // return address on the stack. 990 // return address on the stack.
840 ASSERT(byte_length % 2 == 0); 991 ASSERT(byte_length % 2 == 0);
841 Address buffer_address = reinterpret_cast<Address>(*buffer); 992 Address buffer_address = reinterpret_cast<Address>(*buffer);
842 uc16* substring1 = reinterpret_cast<uc16*>(buffer_address + byte_offset1); 993 uc16* substring1 = reinterpret_cast<uc16*>(buffer_address + byte_offset1);
(...skipping 22 matching lines...) Expand all
865 if (StackGuard::IsStackOverflow()) { 1016 if (StackGuard::IsStackOverflow()) {
866 Top::StackOverflow(); 1017 Top::StackOverflow();
867 return 1; 1018 return 1;
868 } 1019 }
869 1020
870 // If not real stack overflow the stack guard was used to interrupt 1021 // If not real stack overflow the stack guard was used to interrupt
871 // execution for another purpose. 1022 // execution for another purpose.
872 1023
873 // Prepare for possible GC. 1024 // Prepare for possible GC.
874 Handle<Code> code_handle(re_code); 1025 Handle<Code> code_handle(re_code);
875 #ifdef DEBUG 1026
876 CHECK(re_code->instruction_start() <= return_address); 1027 ASSERT(re_code->instruction_start() <= return_address);
877 CHECK(return_address <= 1028 ASSERT(return_address <=
878 re_code->instruction_start() + re_code->instruction_size()); 1029 re_code->instruction_start() + re_code->instruction_size());
879 #endif
880 1030
881 Object* result = Execution::HandleStackGuardInterrupt(); 1031 Object* result = Execution::HandleStackGuardInterrupt();
882 1032
883 if (*code_handle != re_code) { // Return address no longer valid 1033 if (*code_handle != re_code) { // Return address no longer valid
884 int delta = *code_handle - re_code; 1034 int delta = *code_handle - re_code;
885 *reinterpret_cast<int32_t*>(return_address) += delta; 1035 *reinterpret_cast<int32_t*>(return_address) += delta;
886 } 1036 }
887 1037
888 if (result->IsException()) { 1038 if (result->IsException()) {
889 return 1; 1039 return 1;
890 } 1040 }
891 return 0; 1041 return 0;
892 } 1042 }
893 1043
894 1044
1045 Address RegExpMacroAssemblerIA32::GrowStack(Address stack_top) {
1046 size_t size = RegExpStack::stack_capacity();
1047 Address old_stack_end = RegExpStack::stack_top();
1048 Address new_stack_end = RegExpStack::EnsureCapacity(size * 2);
1049 if (new_stack_end == NULL) {
1050 return NULL;
1051 }
1052 return stack_top + (new_stack_end - old_stack_end);
1053 }
1054
1055
895 Operand RegExpMacroAssemblerIA32::register_location(int register_index) { 1056 Operand RegExpMacroAssemblerIA32::register_location(int register_index) {
896 ASSERT(register_index < (1<<30)); 1057 ASSERT(register_index < (1<<30));
897 if (num_registers_ <= register_index) { 1058 if (num_registers_ <= register_index) {
898 num_registers_ = register_index + 1; 1059 num_registers_ = register_index + 1;
899 } 1060 }
900 return Operand(ebp, -(register_index + 1) * kPointerSize); 1061 return Operand(ebp, kRegisterZero - register_index * kPointerSize);
901 }
902
903
904 Register RegExpMacroAssemblerIA32::current_character() {
905 return edx;
906 }
907
908
909 size_t RegExpMacroAssemblerIA32::char_size() {
910 return static_cast<size_t>(mode_);
911 } 1062 }
912 1063
913 1064
914 void RegExpMacroAssemblerIA32::CheckPosition(int cp_offset, 1065 void RegExpMacroAssemblerIA32::CheckPosition(int cp_offset,
915 Label* on_outside_input) { 1066 Label* on_outside_input) {
916 __ cmp(edi, -cp_offset * char_size()); 1067 __ cmp(edi, -cp_offset * char_size());
917 BranchOrBacktrack(greater_equal, on_outside_input); 1068 BranchOrBacktrack(greater_equal, on_outside_input);
918 } 1069 }
919 1070
920 1071
921 void RegExpMacroAssemblerIA32::BranchOrBacktrack(Condition condition, 1072 void RegExpMacroAssemblerIA32::BranchOrBacktrack(Condition condition,
922 Label* to) { 1073 Label* to,
1074 Hint hint) {
923 if (condition < 0) { // No condition 1075 if (condition < 0) { // No condition
924 if (to == NULL) { 1076 if (to == NULL) {
925 Backtrack(); 1077 Backtrack();
926 return; 1078 return;
927 } 1079 }
928 __ jmp(to); 1080 __ jmp(to);
929 return; 1081 return;
930 } 1082 }
931 if (to == NULL) { 1083 if (to == NULL) {
932 __ j(condition, &backtrack_label_); 1084 __ j(condition, &backtrack_label_, hint);
933 return; 1085 return;
934 } 1086 }
935 __ j(condition, to); 1087 __ j(condition, to, hint);
936 } 1088 }
937 1089
938 1090
939 void RegExpMacroAssemblerIA32::SafeCall(Label* to) { 1091 void RegExpMacroAssemblerIA32::SafeCall(Label* to) {
940 Label return_to; 1092 Label return_to;
941 __ push(Immediate::CodeRelativeOffset(&return_to)); 1093 __ push(Immediate::CodeRelativeOffset(&return_to));
942 __ jmp(to); 1094 __ jmp(to);
943 __ bind(&return_to); 1095 __ bind(&return_to);
944 } 1096 }
945 1097
946 1098
947 void RegExpMacroAssemblerIA32::SafeReturn() { 1099 void RegExpMacroAssemblerIA32::SafeReturn() {
948 __ pop(ecx); 1100 __ pop(ebx);
949 __ add(Operand(ecx), Immediate(self_)); 1101 __ add(Operand(ebx), Immediate(self_));
950 __ jmp(Operand(ecx)); 1102 __ jmp(Operand(ebx));
1103 }
1104
1105
1106 void RegExpMacroAssemblerIA32::Push(Register source) {
1107 ASSERT(!source.is(backtrack_stackpointer()));
1108 // Notice: This updates flags, unlike normal Push.
1109 __ sub(Operand(backtrack_stackpointer()), Immediate(kPointerSize));
1110 __ mov(Operand(backtrack_stackpointer(), 0), source);
1111 }
1112
1113
1114 void RegExpMacroAssemblerIA32::Push(Immediate value) {
1115 // Notice: This updates flags, unlike normal Push.
1116 __ sub(Operand(backtrack_stackpointer()), Immediate(kPointerSize));
1117 __ mov(Operand(backtrack_stackpointer(), 0), value);
1118 }
1119
1120
1121 void RegExpMacroAssemblerIA32::Pop(Register target) {
1122 ASSERT(!target.is(backtrack_stackpointer()));
1123 __ mov(target, Operand(backtrack_stackpointer(), 0));
1124 // Notice: This updates flags, unlike normal Pop.
1125 __ add(Operand(backtrack_stackpointer()), Immediate(kPointerSize));
1126 }
1127
1128
1129 void RegExpMacroAssemblerIA32::CheckPreemption() {
1130 // Check for preemption.
1131 Label no_preempt;
1132 ExternalReference stack_guard_limit =
1133 ExternalReference::address_of_stack_guard_limit();
1134 __ cmp(esp, Operand::StaticVariable(stack_guard_limit));
1135 __ j(above, &no_preempt, taken);
1136
1137 SafeCall(&check_preempt_label_);
1138
1139 __ bind(&no_preempt);
951 } 1140 }
952 1141
953 1142
954 void RegExpMacroAssemblerIA32::CheckStackLimit() { 1143 void RegExpMacroAssemblerIA32::CheckStackLimit() {
955 if (FLAG_check_stack) { 1144 if (FLAG_check_stack) {
956 // Check for preemption first. 1145 Label no_stack_overflow;
957 Label no_preempt; 1146 ExternalReference stack_limit =
958 // Check for preemption. 1147 ExternalReference::address_of_regexp_stack_limit();
959 ExternalReference stack_guard_limit = 1148 __ cmp(backtrack_stackpointer(), Operand::StaticVariable(stack_limit));
960 ExternalReference::address_of_stack_guard_limit(); 1149 __ j(above, &no_stack_overflow);
961 __ cmp(esp, Operand::StaticVariable(stack_guard_limit));
962 __ j(above, &no_preempt, taken);
963 1150
964 SafeCall(&check_preempt_label_); 1151 SafeCall(&stack_overflow_label_);
965 1152
966 __ bind(&no_preempt); 1153 __ bind(&no_stack_overflow);
967 } 1154 }
968 } 1155 }
969 1156
970 1157
971 void RegExpMacroAssemblerIA32::FrameAlign(int num_arguments) { 1158 void RegExpMacroAssemblerIA32::FrameAlign(int num_arguments) {
972 int frameAlignment = OS::ActivationFrameAlignment(); 1159 int frameAlignment = OS::ActivationFrameAlignment();
973 if (frameAlignment != 0) { 1160 if (frameAlignment != 0) {
974 // Make stack end at alignment and make room for num_arguments words 1161 // Make stack end at alignment and make room for num_arguments words
975 // and the original value of esp. 1162 // and the original value of esp.
976 __ mov(ebx, esp); 1163 __ mov(ebx, esp);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1022 1209
1023 1210
1024 void RegExpMacroAssemblerIA32::LoadConstantBufferAddress(Register reg, 1211 void RegExpMacroAssemblerIA32::LoadConstantBufferAddress(Register reg,
1025 ArraySlice* buffer) { 1212 ArraySlice* buffer) {
1026 __ mov(reg, buffer->array()); 1213 __ mov(reg, buffer->array());
1027 __ add(Operand(reg), Immediate(buffer->base_offset())); 1214 __ add(Operand(reg), Immediate(buffer->base_offset()));
1028 } 1215 }
1029 1216
1030 #undef __ 1217 #undef __
1031 }} // namespace v8::internal 1218 }} // namespace v8::internal
OLDNEW
« no previous file with comments | « src/regexp-macro-assembler-ia32.h ('k') | src/regexp-macro-assembler-irregexp.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698