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

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

Issue 17416: * Move irregexp backtrack stack to external memory area, instead of the system stack. (Closed)
Patch Set: Added explicit stack check requests to push operations. 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
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 66 * - backup of caller esi
63 * - backup of edi 67 * - backup of caller edi
64 * - backup of ebx 68 * - backup of caller ebx
65 * ebp-> - old ebp 69 * ebp-> - old ebp
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();
113 } 119 }
114 120
115 121
122 int RegExpMacroAssemblerIA32::stack_limit() {
123 return RegExpStack::kStackLimitSlack;
124 }
125
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) {
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
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_);
600 // Save callee-save registers. Order here should correspond to order of 603 // Save callee-save registers. Order here should correspond to order of
601 // kBackup_ebx etc. 604 // kBackup_ebx etc.
602 __ push(esi); 605 __ push(esi);
603 __ push(edi); 606 __ push(edi);
604 __ push(ebx); // Callee-save on MacOS. 607 __ push(ebx); // Callee-save on MacOS.
608
609 // Check if we have space on the stack for registers.
610 Label retry_stack_check;
611 Label stack_limit_hit;
612 Label stack_ok;
613
614 __ bind(&retry_stack_check);
615 ExternalReference stack_guard_limit =
616 ExternalReference::address_of_stack_guard_limit();
617 __ mov(ecx, esp);
618 __ sub(ecx, Operand::StaticVariable(stack_guard_limit));
619 // Handle it if the stack pointer is already below the stack limit.
620 __ j(below_equal, &stack_limit_hit, not_taken);
621 // Check if there is room for num_registers + ebp above the stack limit.
622 __ cmp(ecx, (num_registers_ + 1) * kPointerSize);
623 __ j(above_equal, &stack_ok, taken);
624 // Exit with exception.
625 __ mov(eax, EXCEPTION);
626 Label exit_without_leave;
627 __ jmp(&exit_without_leave);
628
629 __ bind(&stack_limit_hit);
630 int num_arguments = 2;
631 FrameAlign(num_arguments);
632 __ mov(Operand(esp, 1 * kPointerSize), Immediate(self_));
633 __ lea(eax, Operand(esp, -kPointerSize));
634 __ mov(Operand(esp, 0 * kPointerSize), eax);
635 CallCFunction(FUNCTION_ADDR(&CheckStackGuardState), num_arguments);
636 __ or_(eax, Operand(eax));
637 // If returned value is non-zero, the stack guard reports the actual
638 // stack limit being hit and an exception has already been raised.
639 // Otherwise it was a preemption and we just check the limit again.
640 __ j(equal, &retry_stack_check);
641 // Return value was non-zero. Exit with exception.
642 __ mov(eax, EXCEPTION);
643 __ jmp(&exit_without_leave);
644
645 __ bind(&stack_ok);
646
647 // Allocate space on stack for registers.
605 __ enter(Immediate(num_registers_ * kPointerSize)); 648 __ enter(Immediate(num_registers_ * kPointerSize));
606 // Load string length. 649 // Load string length.
607 __ mov(esi, Operand(ebp, kInputEndOffset)); 650 __ mov(esi, Operand(ebp, kInputEndOffset));
608 // Load input position. 651 // Load input position.
609 __ mov(edi, Operand(ebp, kInputStartOffset)); 652 __ mov(edi, Operand(ebp, kInputStartOffset));
610 // Set up edi to be negative offset from string end. 653 // Set up edi to be negative offset from string end.
611 __ sub(edi, Operand(esi)); 654 __ sub(edi, Operand(esi));
612 // Set up esi to be end of string. First get location. 655 // Set up esi to be end of string. First get location.
613 __ mov(edx, Operand(ebp, kInputBuffer)); 656 __ mov(edx, Operand(ebp, kInputBuffer));
614 // Dereference location to get string start. 657 // Dereference location to get string start.
615 __ mov(edx, Operand(edx, 0)); 658 __ mov(edx, Operand(edx, 0));
616 // Add start to length to complete esi setup. 659 // Add start to length to complete esi setup.
617 __ add(esi, Operand(edx)); 660 __ add(esi, Operand(edx));
618 if (num_saved_registers_ > 0) { 661 if (num_saved_registers_ > 0) {
619 // Fill saved registers with initial value = start offset - 1 662 // Fill saved registers with initial value = start offset - 1
620 __ mov(ecx, -num_saved_registers_); 663 // Fill in stack push order, to avoid accessing across an unwritten
621 __ mov(eax, Operand(edi)); 664 // page (a problem on Windows).
622 __ sub(Operand(eax), Immediate(char_size())); 665 __ mov(ecx, -1); // Word offset of register 0 relative to ebp.
Erik Corry 2009/01/12 11:50:13 I can't make out what this comment above means.
666 // Set eax to address of char before start of input.
667 __ lea(eax, Operand(edi, -char_size()));
623 Label init_loop; 668 Label init_loop;
624 __ bind(&init_loop); 669 __ bind(&init_loop);
625 __ mov(Operand(ebp, ecx, times_4, +0), eax); 670 __ mov(Operand(ebp, ecx, times_4, +0), eax);
626 __ inc(ecx); 671 __ dec(ecx);
Erik Corry 2009/01/12 11:50:13 Please avoid dec due to partial flags update perfo
627 __ j(not_equal, &init_loop); 672 __ cmp(ecx, -num_saved_registers_);
673 __ j(greater_equal, &init_loop);
628 } 674 }
675 // Ensure that we have written to each stack page. Skipping a page on
676 // Windows can cause segmentation faults. Assuming page size is 4k.
677 const int kPageSize = 4096;
678 const int kRegistersPerPage = kPageSize / kPointerSize;
679 for(int i = num_saved_registers_ + kRegistersPerPage - 1;
680 i < num_registers_; i += kRegistersPerPage) {
Erik Corry 2009/01/12 11:50:13 for(...;...;...) should be either all on one line
Lasse Reichstein 2009/01/12 13:03:59 Done.
681 __ mov(register_location(i), eax); // One write every page.
Erik Corry 2009/01/12 11:50:13 Please add a test that executes this line if there
Lasse Reichstein 2009/01/12 13:03:59 Done.
682 }
683
684
685 // Initialize backtrack stack pointer.
686 __ mov(backtrack_stackpointer(), Operand(ebp, kStackHighEnd));
629 // Load previous char as initial value of current-character. 687 // Load previous char as initial value of current-character.
630 Label at_start; 688 Label at_start;
631 __ cmp(Operand(ebp, kAtStart), Immediate(0)); 689 __ cmp(Operand(ebp, kAtStart), Immediate(0));
632 __ j(not_equal, &at_start); 690 __ j(not_equal, &at_start);
633 LoadCurrentCharacterUnchecked(-1, 1); // Load previous char. 691 LoadCurrentCharacterUnchecked(-1, 1); // Load previous char.
634 __ jmp(&start_label_); 692 __ jmp(&start_label_);
635 __ bind(&at_start); 693 __ bind(&at_start);
636 __ mov(current_character(), '\n'); 694 __ mov(current_character(), '\n');
637 __ jmp(&start_label_); 695 __ jmp(&start_label_);
638 696
639 697
640 // Exit code: 698 // Exit code:
641 if (success_label_.is_linked()) { 699 if (success_label_.is_linked()) {
642 // Success 700 // Success
643 __ bind(&success_label_); 701 __ bind(&success_label_);
644 if (num_saved_registers_ > 0) { 702 if (num_saved_registers_ > 0) {
645 // copy captures to output 703 // copy captures to output
646 __ mov(ebx, Operand(ebp, kRegisterOutput)); 704 __ mov(ebx, Operand(ebp, kRegisterOutput));
647 __ mov(ecx, Operand(ebp, kInputEndOffset)); 705 __ mov(ecx, Operand(ebp, kInputEndOffset));
648 __ sub(ecx, Operand(ebp, kInputStartOffset)); 706 __ sub(ecx, Operand(ebp, kInputStartOffset));
649 for (int i = 0; i < num_saved_registers_; i++) { 707 for (int i = 0; i < num_saved_registers_; i++) {
650 __ mov(eax, register_location(i)); 708 __ mov(eax, register_location(i));
651 __ add(eax, Operand(ecx)); // Convert to index from start, not end. 709 __ add(eax, Operand(ecx)); // Convert to index from start, not end.
652 if (mode_ == UC16) { 710 if (mode_ == UC16) {
653 __ sar(eax, 1); // Convert byte index to character index. 711 __ sar(eax, 1); // Convert byte index to character index.
654 } 712 }
655 __ mov(Operand(ebx, i * kPointerSize), eax); 713 __ mov(Operand(ebx, i * kPointerSize), eax);
656 } 714 }
657 } 715 }
658 __ mov(eax, Immediate(1)); 716 __ mov(eax, Immediate(SUCCESS));
659 } 717 }
660 // Exit and return eax 718 // Exit and return eax
661 __ bind(&exit_label_); 719 __ bind(&exit_label_);
662 __ leave(); 720 __ leave();
721 __ bind(&exit_without_leave); // For exiting before doing enter.
663 __ pop(ebx); 722 __ pop(ebx);
664 __ pop(edi); 723 __ pop(edi);
665 __ pop(esi); 724 __ pop(esi);
666 __ ret(0); 725 __ ret(0);
667 726
668 // Backtrack code (branch target for conditional backtracks). 727 // Backtrack code (branch target for conditional backtracks).
669 if (backtrack_label_.is_linked()) { 728 if (backtrack_label_.is_linked()) {
670 __ bind(&backtrack_label_); 729 __ bind(&backtrack_label_);
671 Backtrack(); 730 Backtrack();
672 } 731 }
673 732
733 Label exit_with_exception;
734
674 // Preempt-code 735 // Preempt-code
675 if (check_preempt_label_.is_linked()) { 736 if (check_preempt_label_.is_linked()) {
676 __ bind(&check_preempt_label_); 737 __ bind(&check_preempt_label_);
677 // TODO(lrn): call C function to check the stack guard and return current 738
678 // stack state (0 = ok, positive = out of stack, negative = preempt). 739 __ push(backtrack_stackpointer());
679 // Then dispatch to an action depending on state, and loop.
680 __ push(edi); 740 __ push(edi);
681 741
682 Label retry; 742 Label retry;
683 Label stack_overflow;
684 743
685 __ bind(&retry); 744 __ bind(&retry);
686 int num_arguments = 2; 745 int num_arguments = 2;
687 FrameAlign(num_arguments); 746 FrameAlign(num_arguments);
688 __ mov(Operand(esp, 1 * kPointerSize), Immediate(self_)); 747 __ mov(Operand(esp, 1 * kPointerSize), Immediate(self_));
689 __ lea(eax, Operand(esp, -kPointerSize)); 748 __ lea(eax, Operand(esp, -kPointerSize));
690 __ mov(Operand(esp, 0 * kPointerSize), eax); 749 __ mov(Operand(esp, 0 * kPointerSize), eax);
691 CallCFunction(FUNCTION_ADDR(&CheckStackGuardState), num_arguments); 750 CallCFunction(FUNCTION_ADDR(&CheckStackGuardState), num_arguments);
751 // Return value must be zero. We cannot have a stack overflow at
752 // this point, since we checked the stack on entry and haven't
753 // pushed anything since, that we haven't also popped again.
692 754
693 ExternalReference stack_guard_limit = 755 ExternalReference stack_guard_limit =
694 ExternalReference::address_of_stack_guard_limit(); 756 ExternalReference::address_of_stack_guard_limit();
695 757 // 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)); 758 __ cmp(esp, Operand::StaticVariable(stack_guard_limit));
700 __ j(below_equal, &retry); 759 __ j(below_equal, &retry);
701 760
702 __ pop(edi); 761 __ pop(edi);
762 __ pop(backtrack_stackpointer());
703 // String might have moved: Recompute esi from scratch. 763 // String might have moved: Recompute esi from scratch.
704 __ mov(esi, Operand(esp, kInputBuffer)); 764 __ mov(esi, Operand(ebp, kInputBuffer));
705 __ mov(esi, Operand(esi, 0)); 765 __ mov(esi, Operand(esi, 0));
706 __ add(esi, Operand(esp, kInputEndOffset)); 766 __ add(esi, Operand(ebp, kInputEndOffset));
707 SafeReturn(); 767 SafeReturn();
768 }
708 769
709 __ bind(&stack_overflow); 770 // Backtrack stack overflow code.
710 // Exit with result -1 to signal thrown exception. 771 if (stack_overflow_label_.is_linked()) {
711 __ mov(eax, -1); 772 __ bind(&stack_overflow_label_);
773 // Reached if the backtrack-stack limit has been hit.
774
775 Label grow_failed;
776 // Save registers before calling C function
777 __ push(esi);
778 __ push(edi);
779
780 // Call GrowStack(backtrack_stackpointer())
781 int num_arguments = 1;
782 FrameAlign(num_arguments);
783 __ mov(Operand(esp, 0), backtrack_stackpointer());
784 CallCFunction(FUNCTION_ADDR(&GrowStack), num_arguments);
785 // If return NULL, we have failed to grow the stack, and
786 // must exit with a stack-overflow exception.
787 __ or_(eax, Operand(eax));
788 __ j(equal, &exit_with_exception);
789 // Otherwise use return value as new stack pointer.
790 __ mov(backtrack_stackpointer(), eax);
791 // Restore saved registers and continue.
792 __ pop(edi);
793 __ pop(esi);
794 SafeReturn();
795 }
796
797 if (exit_with_exception.is_linked()) {
798 // If any of the code above needed to exit with an exception.
799 __ bind(&exit_with_exception);
800 // Exit with Result EXCEPTION(-1) to signal thrown exception.
801 __ mov(eax, EXCEPTION);
712 __ jmp(&exit_label_); 802 __ jmp(&exit_label_);
713 } 803 }
714 804
715 CodeDesc code_desc; 805 CodeDesc code_desc;
716 masm_->GetCode(&code_desc); 806 masm_->GetCode(&code_desc);
717 Handle<Code> code = Factory::NewCode(code_desc, 807 Handle<Code> code = Factory::NewCode(code_desc,
718 NULL, 808 NULL,
719 Code::ComputeFlags(Code::REGEXP), 809 Code::ComputeFlags(Code::REGEXP),
720 self_); 810 self_);
721 LOG(CodeCreateEvent("RegExp", *code, *(source->ToCString()))); 811 LOG(CodeCreateEvent("RegExp", *code, *(source->ToCString())));
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
762 bool check_bounds, 852 bool check_bounds,
763 int characters) { 853 int characters) {
764 ASSERT(cp_offset >= 0); 854 ASSERT(cp_offset >= 0);
765 ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works) 855 ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works)
766 CheckPosition(cp_offset + characters - 1, on_end_of_input); 856 CheckPosition(cp_offset + characters - 1, on_end_of_input);
767 LoadCurrentCharacterUnchecked(cp_offset, characters); 857 LoadCurrentCharacterUnchecked(cp_offset, characters);
768 } 858 }
769 859
770 860
771 void RegExpMacroAssemblerIA32::PopCurrentPosition() { 861 void RegExpMacroAssemblerIA32::PopCurrentPosition() {
772 __ pop(edi); 862 Pop(edi);
773 } 863 }
774 864
775 865
776 void RegExpMacroAssemblerIA32::PopRegister(int register_index) { 866 void RegExpMacroAssemblerIA32::PopRegister(int register_index) {
777 __ pop(register_location(register_index)); 867 Pop(eax);
868 __ mov(register_location(register_index), eax);
778 } 869 }
779 870
780 871
781 void RegExpMacroAssemblerIA32::PushBacktrack(Label* label) { 872 void RegExpMacroAssemblerIA32::PushBacktrack(Label* label,
782 __ push(Immediate::CodeRelativeOffset(label)); 873 StackCheckFlag check_stack_limit) {
874 Push(Immediate::CodeRelativeOffset(label));
783 CheckStackLimit(); 875 CheckStackLimit();
876 if (check_stack_limit) CheckStackLimit();
Erik Corry 2009/01/12 11:50:13 Checking twice just to be sure? :-)
Lasse Reichstein 2009/01/12 13:03:59 Better safe and safe than sorry and sorry. Fixed.
784 } 877 }
785 878
786 879
787 void RegExpMacroAssemblerIA32::PushCurrentPosition() { 880 void RegExpMacroAssemblerIA32::PushCurrentPosition(
788 __ push(edi); 881 StackCheckFlag check_stack_limit) {
882 Push(edi);
883 if (check_stack_limit) CheckStackLimit();
789 } 884 }
790 885
791 886
792 void RegExpMacroAssemblerIA32::PushRegister(int register_index) { 887 void RegExpMacroAssemblerIA32::PushRegister(int register_index,
793 __ push(register_location(register_index)); 888 StackCheckFlag check_stack_limit) {
889 __ mov(eax, register_location(register_index));
890 Push(eax);
891 if (check_stack_limit) CheckStackLimit();
794 } 892 }
795 893
796 894
797 void RegExpMacroAssemblerIA32::ReadCurrentPositionFromRegister(int reg) { 895 void RegExpMacroAssemblerIA32::ReadCurrentPositionFromRegister(int reg) {
798 __ mov(edi, register_location(reg)); 896 __ mov(edi, register_location(reg));
799 } 897 }
800 898
801 899
802 void RegExpMacroAssemblerIA32::ReadStackPointerFromRegister(int reg) { 900 void RegExpMacroAssemblerIA32::ReadStackPointerFromRegister(int reg) {
803 __ mov(esp, register_location(reg)); 901 __ mov(backtrack_stackpointer(), register_location(reg));
804 } 902 }
805 903
806 904
807 void RegExpMacroAssemblerIA32::SetRegister(int register_index, int to) { 905 void RegExpMacroAssemblerIA32::SetRegister(int register_index, int to) {
808 ASSERT(register_index >= num_saved_registers_); // Reserved for positions! 906 ASSERT(register_index >= num_saved_registers_); // Reserved for positions!
809 __ mov(register_location(register_index), Immediate(to)); 907 __ mov(register_location(register_index), Immediate(to));
810 } 908 }
811 909
812 910
813 void RegExpMacroAssemblerIA32::Succeed() { 911 void RegExpMacroAssemblerIA32::Succeed() {
814 __ jmp(&success_label_); 912 __ jmp(&success_label_);
815 } 913 }
816 914
817 915
818 void RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister(int reg, 916 void RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister(int reg,
819 int cp_offset) { 917 int cp_offset) {
820 if (cp_offset == 0) { 918 if (cp_offset == 0) {
821 __ mov(register_location(reg), edi); 919 __ mov(register_location(reg), edi);
822 } else { 920 } else {
823 __ lea(eax, Operand(edi, cp_offset * char_size())); 921 __ lea(eax, Operand(edi, cp_offset * char_size()));
824 __ mov(register_location(reg), eax); 922 __ mov(register_location(reg), eax);
825 } 923 }
826 } 924 }
827 925
828 926
829 void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) { 927 void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) {
830 __ mov(register_location(reg), esp); 928 __ mov(register_location(reg), backtrack_stackpointer());
831 } 929 }
832 930
833 931
834 // Private methods: 932 // Private methods:
835 933
836 934
837 static unibrow::Mapping<unibrow::Ecma262Canonicalize> canonicalize; 935 static unibrow::Mapping<unibrow::Ecma262Canonicalize> canonicalize;
838 936
839 937
938 RegExpMacroAssemblerIA32::Result RegExpMacroAssemblerIA32::Execute(
939 Code* code,
940 Address* input,
941 int start_offset,
942 int end_offset,
943 int* output,
944 bool at_start) {
945 typedef int (*matcher)(Address*, int, int, int*, int, void*);
946 matcher matcher_func = FUNCTION_CAST<matcher>(code->entry());
947
948 int at_start_val = at_start ? 1 : 0;
949
950 // Ensure that the minimum stack has been allocated.
951 RegExpStack stack;
952 void* stack_top = RegExpStack::stack_top();
953
954 int result = matcher_func(input,
955 start_offset,
956 end_offset,
957 output,
958 at_start_val,
959 stack_top);
960
961 if (result < 0 && !Top::has_pending_exception()) {
962 // We detected a stack overflow in RegExp code, but haven't created
963 // the exception yet.
964 Top::StackOverflow();
965 }
966 return (result < 0) ? EXCEPTION : (result ? SUCCESS : FAILURE);
967 }
968
969
840 int RegExpMacroAssemblerIA32::CaseInsensitiveCompareUC16(uc16** buffer, 970 int RegExpMacroAssemblerIA32::CaseInsensitiveCompareUC16(uc16** buffer,
841 int byte_offset1, 971 int byte_offset1,
842 int byte_offset2, 972 int byte_offset2,
843 size_t byte_length) { 973 size_t byte_length) {
844 // This function is not allowed to cause a garbage collection. 974 // This function is not allowed to cause a garbage collection.
845 // A GC might move the calling generated code and invalidate the 975 // A GC might move the calling generated code and invalidate the
846 // return address on the stack. 976 // return address on the stack.
847 ASSERT(byte_length % 2 == 0); 977 ASSERT(byte_length % 2 == 0);
848 Address buffer_address = reinterpret_cast<Address>(*buffer); 978 Address buffer_address = reinterpret_cast<Address>(*buffer);
849 uc16* substring1 = reinterpret_cast<uc16*>(buffer_address + byte_offset1); 979 uc16* substring1 = reinterpret_cast<uc16*>(buffer_address + byte_offset1);
(...skipping 22 matching lines...) Expand all
872 if (StackGuard::IsStackOverflow()) { 1002 if (StackGuard::IsStackOverflow()) {
873 Top::StackOverflow(); 1003 Top::StackOverflow();
874 return 1; 1004 return 1;
875 } 1005 }
876 1006
877 // If not real stack overflow the stack guard was used to interrupt 1007 // If not real stack overflow the stack guard was used to interrupt
878 // execution for another purpose. 1008 // execution for another purpose.
879 1009
880 // Prepare for possible GC. 1010 // Prepare for possible GC.
881 Handle<Code> code_handle(re_code); 1011 Handle<Code> code_handle(re_code);
882 #ifdef DEBUG 1012
883 CHECK(re_code->instruction_start() <= return_address); 1013 ASSERT(re_code->instruction_start() <= return_address);
884 CHECK(return_address <= 1014 ASSERT(return_address <=
885 re_code->instruction_start() + re_code->instruction_size()); 1015 re_code->instruction_start() + re_code->instruction_size());
886 #endif
887 1016
888 Object* result = Execution::HandleStackGuardInterrupt(); 1017 Object* result = Execution::HandleStackGuardInterrupt();
889 1018
890 if (*code_handle != re_code) { // Return address no longer valid 1019 if (*code_handle != re_code) { // Return address no longer valid
891 int delta = *code_handle - re_code; 1020 int delta = *code_handle - re_code;
892 *reinterpret_cast<int32_t*>(return_address) += delta; 1021 *reinterpret_cast<int32_t*>(return_address) += delta;
893 } 1022 }
894 1023
895 if (result->IsException()) { 1024 if (result->IsException()) {
896 return 1; 1025 return 1;
897 } 1026 }
898 return 0; 1027 return 0;
899 } 1028 }
900 1029
901 1030
1031 Address RegExpMacroAssemblerIA32::GrowStack(Address stack_top) {
1032 size_t size = RegExpStack::stack_capacity();
1033 Address old_stack_end = RegExpStack::stack_top();
1034 Address new_stack_end = RegExpStack::EnsureCapacity(size * 2);
1035 if (new_stack_end == NULL) {
1036 return NULL;
1037 }
1038 return stack_top + (new_stack_end - old_stack_end);
1039 }
1040
1041
902 Operand RegExpMacroAssemblerIA32::register_location(int register_index) { 1042 Operand RegExpMacroAssemblerIA32::register_location(int register_index) {
903 ASSERT(register_index < (1<<30)); 1043 ASSERT(register_index < (1<<30));
904 if (num_registers_ <= register_index) { 1044 if (num_registers_ <= register_index) {
905 num_registers_ = register_index + 1; 1045 num_registers_ = register_index + 1;
906 } 1046 }
907 return Operand(ebp, -(register_index + 1) * kPointerSize); 1047 return Operand(ebp, -(register_index + 1) * kPointerSize);
908 } 1048 }
909 1049
910 1050
911 Register RegExpMacroAssemblerIA32::current_character() {
912 return edx;
913 }
914
915
916 size_t RegExpMacroAssemblerIA32::char_size() {
917 return static_cast<size_t>(mode_);
918 }
919
920
921 void RegExpMacroAssemblerIA32::CheckPosition(int cp_offset, 1051 void RegExpMacroAssemblerIA32::CheckPosition(int cp_offset,
922 Label* on_outside_input) { 1052 Label* on_outside_input) {
923 __ cmp(edi, -cp_offset * char_size()); 1053 __ cmp(edi, -cp_offset * char_size());
924 BranchOrBacktrack(greater_equal, on_outside_input); 1054 BranchOrBacktrack(greater_equal, on_outside_input);
925 } 1055 }
926 1056
927 1057
928 void RegExpMacroAssemblerIA32::BranchOrBacktrack(Condition condition, 1058 void RegExpMacroAssemblerIA32::BranchOrBacktrack(Condition condition,
929 Label* to) { 1059 Label* to,
1060 Hint hint) {
930 if (condition < 0) { // No condition 1061 if (condition < 0) { // No condition
931 if (to == NULL) { 1062 if (to == NULL) {
932 Backtrack(); 1063 Backtrack();
933 return; 1064 return;
934 } 1065 }
935 __ jmp(to); 1066 __ jmp(to);
936 return; 1067 return;
937 } 1068 }
938 if (to == NULL) { 1069 if (to == NULL) {
939 __ j(condition, &backtrack_label_); 1070 __ j(condition, &backtrack_label_, hint);
940 return; 1071 return;
941 } 1072 }
942 __ j(condition, to); 1073 __ j(condition, to, hint);
943 } 1074 }
944 1075
945 1076
946 void RegExpMacroAssemblerIA32::SafeCall(Label* to) { 1077 void RegExpMacroAssemblerIA32::SafeCall(Label* to) {
947 Label return_to; 1078 Label return_to;
948 __ push(Immediate::CodeRelativeOffset(&return_to)); 1079 __ push(Immediate::CodeRelativeOffset(&return_to));
949 __ jmp(to); 1080 __ jmp(to);
950 __ bind(&return_to); 1081 __ bind(&return_to);
951 } 1082 }
952 1083
953 1084
954 void RegExpMacroAssemblerIA32::SafeReturn() { 1085 void RegExpMacroAssemblerIA32::SafeReturn() {
955 __ pop(ecx); 1086 __ pop(ebx);
956 __ add(Operand(ecx), Immediate(self_)); 1087 __ add(Operand(ebx), Immediate(self_));
957 __ jmp(Operand(ecx)); 1088 __ jmp(Operand(ebx));
1089 }
1090
1091
1092 void RegExpMacroAssemblerIA32::Push(Register source) {
1093 ASSERT(!source.is(backtrack_stackpointer()));
1094 // Notice: This updates flags, unlike normal Push.
1095 __ sub(Operand(backtrack_stackpointer()), Immediate(kPointerSize));
1096 __ mov(Operand(backtrack_stackpointer(), 0), source);
1097 }
1098
1099
1100 void RegExpMacroAssemblerIA32::Push(Immediate value) {
1101 // Notice: This updates flags, unlike normal Push.
1102 __ sub(Operand(backtrack_stackpointer()), Immediate(kPointerSize));
1103 __ mov(Operand(backtrack_stackpointer(), 0), value);
1104 }
1105
1106
1107 void RegExpMacroAssemblerIA32::Pop(Register target) {
1108 ASSERT(!target.is(backtrack_stackpointer()));
1109 __ mov(target, Operand(backtrack_stackpointer(), 0));
1110 // Notice: This updates flags, unlike normal Pop.
1111 __ add(Operand(backtrack_stackpointer()), Immediate(kPointerSize));
1112 }
1113
1114
1115 void RegExpMacroAssemblerIA32::CheckPreemption() {
1116 // Check for preemption.
1117 Label no_preempt;
1118 ExternalReference stack_guard_limit =
1119 ExternalReference::address_of_stack_guard_limit();
1120 __ cmp(esp, Operand::StaticVariable(stack_guard_limit));
1121 __ j(above, &no_preempt, taken);
1122
1123 SafeCall(&check_preempt_label_);
1124
1125 __ bind(&no_preempt);
958 } 1126 }
959 1127
960 1128
961 void RegExpMacroAssemblerIA32::CheckStackLimit() { 1129 void RegExpMacroAssemblerIA32::CheckStackLimit() {
962 if (FLAG_check_stack) { 1130 if (FLAG_check_stack) {
963 // Check for preemption first. 1131 Label no_stack_overflow;
964 Label no_preempt; 1132 ExternalReference stack_limit =
965 // Check for preemption. 1133 ExternalReference::address_of_regexp_stack_limit();
966 ExternalReference stack_guard_limit = 1134 __ cmp(backtrack_stackpointer(), Operand::StaticVariable(stack_limit));
967 ExternalReference::address_of_stack_guard_limit(); 1135 __ j(above, &no_stack_overflow);
968 __ cmp(esp, Operand::StaticVariable(stack_guard_limit));
969 __ j(above, &no_preempt, taken);
970 1136
971 SafeCall(&check_preempt_label_); 1137 SafeCall(&stack_overflow_label_);
972 1138
973 __ bind(&no_preempt); 1139 __ bind(&no_stack_overflow);
974 } 1140 }
975 } 1141 }
976 1142
977 1143
978 void RegExpMacroAssemblerIA32::FrameAlign(int num_arguments) { 1144 void RegExpMacroAssemblerIA32::FrameAlign(int num_arguments) {
979 int frameAlignment = OS::ActivationFrameAlignment(); 1145 int frameAlignment = OS::ActivationFrameAlignment();
980 if (frameAlignment != 0) { 1146 if (frameAlignment != 0) {
981 // Make stack end at alignment and make room for num_arguments words 1147 // Make stack end at alignment and make room for num_arguments words
982 // and the original value of esp. 1148 // and the original value of esp.
983 __ mov(ebx, esp); 1149 __ mov(ebx, esp);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1029 1195
1030 1196
1031 void RegExpMacroAssemblerIA32::LoadConstantBufferAddress(Register reg, 1197 void RegExpMacroAssemblerIA32::LoadConstantBufferAddress(Register reg,
1032 ArraySlice* buffer) { 1198 ArraySlice* buffer) {
1033 __ mov(reg, buffer->array()); 1199 __ mov(reg, buffer->array());
1034 __ add(Operand(reg), Immediate(buffer->base_offset())); 1200 __ add(Operand(reg), Immediate(buffer->base_offset()));
1035 } 1201 }
1036 1202
1037 #undef __ 1203 #undef __
1038 }} // namespace v8::internal 1204 }} // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698