| OLD | NEW |
| 1 // Copyright 2008-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 |
| 11 // with the distribution. | 11 // with the distribution. |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 } | 127 } |
| 128 | 128 |
| 129 | 129 |
| 130 int RegExpMacroAssemblerIA32::stack_limit_slack() { | 130 int RegExpMacroAssemblerIA32::stack_limit_slack() { |
| 131 return RegExpStack::kStackLimitSlack; | 131 return RegExpStack::kStackLimitSlack; |
| 132 } | 132 } |
| 133 | 133 |
| 134 | 134 |
| 135 void RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) { | 135 void RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) { |
| 136 if (by != 0) { | 136 if (by != 0) { |
| 137 __ add(Operand(edi), Immediate(by * char_size())); | 137 __ add(edi, Immediate(by * char_size())); |
| 138 } | 138 } |
| 139 } | 139 } |
| 140 | 140 |
| 141 | 141 |
| 142 void RegExpMacroAssemblerIA32::AdvanceRegister(int reg, int by) { | 142 void RegExpMacroAssemblerIA32::AdvanceRegister(int reg, int by) { |
| 143 ASSERT(reg >= 0); | 143 ASSERT(reg >= 0); |
| 144 ASSERT(reg < num_registers_); | 144 ASSERT(reg < num_registers_); |
| 145 if (by != 0) { | 145 if (by != 0) { |
| 146 __ add(register_location(reg), Immediate(by)); | 146 __ add(register_location(reg), Immediate(by)); |
| 147 } | 147 } |
| 148 } | 148 } |
| 149 | 149 |
| 150 | 150 |
| 151 void RegExpMacroAssemblerIA32::Backtrack() { | 151 void RegExpMacroAssemblerIA32::Backtrack() { |
| 152 CheckPreemption(); | 152 CheckPreemption(); |
| 153 // Pop Code* offset from backtrack stack, add Code* and jump to location. | 153 // Pop Code* offset from backtrack stack, add Code* and jump to location. |
| 154 Pop(ebx); | 154 Pop(ebx); |
| 155 __ add(Operand(ebx), Immediate(masm_->CodeObject())); | 155 __ add(ebx, Immediate(masm_->CodeObject())); |
| 156 __ jmp(Operand(ebx)); | 156 __ jmp(ebx); |
| 157 } | 157 } |
| 158 | 158 |
| 159 | 159 |
| 160 void RegExpMacroAssemblerIA32::Bind(Label* label) { | 160 void RegExpMacroAssemblerIA32::Bind(Label* label) { |
| 161 __ bind(label); | 161 __ bind(label); |
| 162 } | 162 } |
| 163 | 163 |
| 164 | 164 |
| 165 void RegExpMacroAssemblerIA32::CheckCharacter(uint32_t c, Label* on_equal) { | 165 void RegExpMacroAssemblerIA32::CheckCharacter(uint32_t c, Label* on_equal) { |
| 166 __ cmp(current_character(), c); | 166 __ cmp(current_character(), c); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 // If input is ASCII, don't even bother calling here if the string to | 212 // If input is ASCII, don't even bother calling here if the string to |
| 213 // match contains a non-ascii character. | 213 // match contains a non-ascii character. |
| 214 if (mode_ == ASCII) { | 214 if (mode_ == ASCII) { |
| 215 ASSERT(String::IsAscii(str.start(), str.length())); | 215 ASSERT(String::IsAscii(str.start(), str.length())); |
| 216 } | 216 } |
| 217 #endif | 217 #endif |
| 218 int byte_length = str.length() * char_size(); | 218 int byte_length = str.length() * char_size(); |
| 219 int byte_offset = cp_offset * char_size(); | 219 int byte_offset = cp_offset * char_size(); |
| 220 if (check_end_of_string) { | 220 if (check_end_of_string) { |
| 221 // Check that there are at least str.length() characters left in the input. | 221 // Check that there are at least str.length() characters left in the input. |
| 222 __ cmp(Operand(edi), Immediate(-(byte_offset + byte_length))); | 222 __ cmp(edi, Immediate(-(byte_offset + byte_length))); |
| 223 BranchOrBacktrack(greater, on_failure); | 223 BranchOrBacktrack(greater, on_failure); |
| 224 } | 224 } |
| 225 | 225 |
| 226 if (on_failure == NULL) { | 226 if (on_failure == NULL) { |
| 227 // Instead of inlining a backtrack, (re)use the global backtrack target. | 227 // Instead of inlining a backtrack, (re)use the global backtrack target. |
| 228 on_failure = &backtrack_label_; | 228 on_failure = &backtrack_label_; |
| 229 } | 229 } |
| 230 | 230 |
| 231 // Do one character test first to minimize loading for the case that | 231 // Do one character test first to minimize loading for the case that |
| 232 // we don't match at all (loading more than one character introduces that | 232 // we don't match at all (loading more than one character introduces that |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 281 } | 281 } |
| 282 BranchOrBacktrack(not_equal, on_failure); | 282 BranchOrBacktrack(not_equal, on_failure); |
| 283 } | 283 } |
| 284 } | 284 } |
| 285 | 285 |
| 286 | 286 |
| 287 void RegExpMacroAssemblerIA32::CheckGreedyLoop(Label* on_equal) { | 287 void RegExpMacroAssemblerIA32::CheckGreedyLoop(Label* on_equal) { |
| 288 Label fallthrough; | 288 Label fallthrough; |
| 289 __ cmp(edi, Operand(backtrack_stackpointer(), 0)); | 289 __ cmp(edi, Operand(backtrack_stackpointer(), 0)); |
| 290 __ j(not_equal, &fallthrough); | 290 __ j(not_equal, &fallthrough); |
| 291 __ add(Operand(backtrack_stackpointer()), Immediate(kPointerSize)); // Pop. | 291 __ add(backtrack_stackpointer(), Immediate(kPointerSize)); // Pop. |
| 292 BranchOrBacktrack(no_condition, on_equal); | 292 BranchOrBacktrack(no_condition, on_equal); |
| 293 __ bind(&fallthrough); | 293 __ bind(&fallthrough); |
| 294 } | 294 } |
| 295 | 295 |
| 296 | 296 |
| 297 void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase( | 297 void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase( |
| 298 int start_reg, | 298 int start_reg, |
| 299 Label* on_no_match) { | 299 Label* on_no_match) { |
| 300 Label fallthrough; | 300 Label fallthrough; |
| 301 __ mov(edx, register_location(start_reg)); // Index of start of capture | 301 __ mov(edx, register_location(start_reg)); // Index of start of capture |
| 302 __ mov(ebx, register_location(start_reg + 1)); // Index of end of capture | 302 __ mov(ebx, register_location(start_reg + 1)); // Index of end of capture |
| 303 __ sub(ebx, Operand(edx)); // Length of capture. | 303 __ sub(ebx, edx); // Length of capture. |
| 304 | 304 |
| 305 // The length of a capture should not be negative. This can only happen | 305 // The length of a capture should not be negative. This can only happen |
| 306 // if the end of the capture is unrecorded, or at a point earlier than | 306 // if the end of the capture is unrecorded, or at a point earlier than |
| 307 // the start of the capture. | 307 // the start of the capture. |
| 308 BranchOrBacktrack(less, on_no_match); | 308 BranchOrBacktrack(less, on_no_match); |
| 309 | 309 |
| 310 // If length is zero, either the capture is empty or it is completely | 310 // If length is zero, either the capture is empty or it is completely |
| 311 // uncaptured. In either case succeed immediately. | 311 // uncaptured. In either case succeed immediately. |
| 312 __ j(equal, &fallthrough); | 312 __ j(equal, &fallthrough); |
| 313 | 313 |
| 314 if (mode_ == ASCII) { | 314 if (mode_ == ASCII) { |
| 315 Label success; | 315 Label success; |
| 316 Label fail; | 316 Label fail; |
| 317 Label loop_increment; | 317 Label loop_increment; |
| 318 // Save register contents to make the registers available below. | 318 // Save register contents to make the registers available below. |
| 319 __ push(edi); | 319 __ push(edi); |
| 320 __ push(backtrack_stackpointer()); | 320 __ push(backtrack_stackpointer()); |
| 321 // After this, the eax, ecx, and edi registers are available. | 321 // After this, the eax, ecx, and edi registers are available. |
| 322 | 322 |
| 323 __ add(edx, Operand(esi)); // Start of capture | 323 __ add(edx, esi); // Start of capture |
| 324 __ add(edi, Operand(esi)); // Start of text to match against capture. | 324 __ add(edi, esi); // Start of text to match against capture. |
| 325 __ add(ebx, Operand(edi)); // End of text to match against capture. | 325 __ add(ebx, edi); // End of text to match against capture. |
| 326 | 326 |
| 327 Label loop; | 327 Label loop; |
| 328 __ bind(&loop); | 328 __ bind(&loop); |
| 329 __ movzx_b(eax, Operand(edi, 0)); | 329 __ movzx_b(eax, Operand(edi, 0)); |
| 330 __ cmpb_al(Operand(edx, 0)); | 330 __ cmpb_al(Operand(edx, 0)); |
| 331 __ j(equal, &loop_increment); | 331 __ j(equal, &loop_increment); |
| 332 | 332 |
| 333 // Mismatch, try case-insensitive match (converting letters to lower-case). | 333 // Mismatch, try case-insensitive match (converting letters to lower-case). |
| 334 __ or_(eax, 0x20); // Convert match character to lower-case. | 334 __ or_(eax, 0x20); // Convert match character to lower-case. |
| 335 __ lea(ecx, Operand(eax, -'a')); | 335 __ lea(ecx, Operand(eax, -'a')); |
| 336 __ cmp(ecx, static_cast<int32_t>('z' - 'a')); // Is eax a lowercase letter? | 336 __ cmp(ecx, static_cast<int32_t>('z' - 'a')); // Is eax a lowercase letter? |
| 337 __ j(above, &fail); | 337 __ j(above, &fail); |
| 338 // Also convert capture character. | 338 // Also convert capture character. |
| 339 __ movzx_b(ecx, Operand(edx, 0)); | 339 __ movzx_b(ecx, Operand(edx, 0)); |
| 340 __ or_(ecx, 0x20); | 340 __ or_(ecx, 0x20); |
| 341 | 341 |
| 342 __ cmp(eax, Operand(ecx)); | 342 __ cmp(eax, ecx); |
| 343 __ j(not_equal, &fail); | 343 __ j(not_equal, &fail); |
| 344 | 344 |
| 345 __ bind(&loop_increment); | 345 __ bind(&loop_increment); |
| 346 // Increment pointers into match and capture strings. | 346 // Increment pointers into match and capture strings. |
| 347 __ add(Operand(edx), Immediate(1)); | 347 __ add(edx, Immediate(1)); |
| 348 __ add(Operand(edi), Immediate(1)); | 348 __ add(edi, Immediate(1)); |
| 349 // Compare to end of match, and loop if not done. | 349 // Compare to end of match, and loop if not done. |
| 350 __ cmp(edi, Operand(ebx)); | 350 __ cmp(edi, ebx); |
| 351 __ j(below, &loop); | 351 __ j(below, &loop); |
| 352 __ jmp(&success); | 352 __ jmp(&success); |
| 353 | 353 |
| 354 __ bind(&fail); | 354 __ bind(&fail); |
| 355 // Restore original values before failing. | 355 // Restore original values before failing. |
| 356 __ pop(backtrack_stackpointer()); | 356 __ pop(backtrack_stackpointer()); |
| 357 __ pop(edi); | 357 __ pop(edi); |
| 358 BranchOrBacktrack(no_condition, on_no_match); | 358 BranchOrBacktrack(no_condition, on_no_match); |
| 359 | 359 |
| 360 __ bind(&success); | 360 __ bind(&success); |
| 361 // Restore original value before continuing. | 361 // Restore original value before continuing. |
| 362 __ pop(backtrack_stackpointer()); | 362 __ pop(backtrack_stackpointer()); |
| 363 // Drop original value of character position. | 363 // Drop original value of character position. |
| 364 __ add(Operand(esp), Immediate(kPointerSize)); | 364 __ add(esp, Immediate(kPointerSize)); |
| 365 // Compute new value of character position after the matched part. | 365 // Compute new value of character position after the matched part. |
| 366 __ sub(edi, Operand(esi)); | 366 __ sub(edi, esi); |
| 367 } else { | 367 } else { |
| 368 ASSERT(mode_ == UC16); | 368 ASSERT(mode_ == UC16); |
| 369 // Save registers before calling C function. | 369 // Save registers before calling C function. |
| 370 __ push(esi); | 370 __ push(esi); |
| 371 __ push(edi); | 371 __ push(edi); |
| 372 __ push(backtrack_stackpointer()); | 372 __ push(backtrack_stackpointer()); |
| 373 __ push(ebx); | 373 __ push(ebx); |
| 374 | 374 |
| 375 static const int argument_count = 4; | 375 static const int argument_count = 4; |
| 376 __ PrepareCallCFunction(argument_count, ecx); | 376 __ PrepareCallCFunction(argument_count, ecx); |
| 377 // Put arguments into allocated stack area, last argument highest on stack. | 377 // Put arguments into allocated stack area, last argument highest on stack. |
| 378 // Parameters are | 378 // Parameters are |
| 379 // Address byte_offset1 - Address captured substring's start. | 379 // Address byte_offset1 - Address captured substring's start. |
| 380 // Address byte_offset2 - Address of current character position. | 380 // Address byte_offset2 - Address of current character position. |
| 381 // size_t byte_length - length of capture in bytes(!) | 381 // size_t byte_length - length of capture in bytes(!) |
| 382 // Isolate* isolate | 382 // Isolate* isolate |
| 383 | 383 |
| 384 // Set isolate. | 384 // Set isolate. |
| 385 __ mov(Operand(esp, 3 * kPointerSize), | 385 __ mov(Operand(esp, 3 * kPointerSize), |
| 386 Immediate(ExternalReference::isolate_address())); | 386 Immediate(ExternalReference::isolate_address())); |
| 387 // Set byte_length. | 387 // Set byte_length. |
| 388 __ mov(Operand(esp, 2 * kPointerSize), ebx); | 388 __ mov(Operand(esp, 2 * kPointerSize), ebx); |
| 389 // Set byte_offset2. | 389 // Set byte_offset2. |
| 390 // Found by adding negative string-end offset of current position (edi) | 390 // Found by adding negative string-end offset of current position (edi) |
| 391 // to end of string. | 391 // to end of string. |
| 392 __ add(edi, Operand(esi)); | 392 __ add(edi, esi); |
| 393 __ mov(Operand(esp, 1 * kPointerSize), edi); | 393 __ mov(Operand(esp, 1 * kPointerSize), edi); |
| 394 // Set byte_offset1. | 394 // Set byte_offset1. |
| 395 // Start of capture, where edx already holds string-end negative offset. | 395 // Start of capture, where edx already holds string-end negative offset. |
| 396 __ add(edx, Operand(esi)); | 396 __ add(edx, esi); |
| 397 __ mov(Operand(esp, 0 * kPointerSize), edx); | 397 __ mov(Operand(esp, 0 * kPointerSize), edx); |
| 398 | 398 |
| 399 ExternalReference compare = | 399 { |
| 400 ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate()); | 400 AllowExternalCallThatCantCauseGC scope(masm_); |
| 401 __ CallCFunction(compare, argument_count); | 401 ExternalReference compare = |
| 402 ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate()); |
| 403 __ CallCFunction(compare, argument_count); |
| 404 } |
| 402 // Pop original values before reacting on result value. | 405 // Pop original values before reacting on result value. |
| 403 __ pop(ebx); | 406 __ pop(ebx); |
| 404 __ pop(backtrack_stackpointer()); | 407 __ pop(backtrack_stackpointer()); |
| 405 __ pop(edi); | 408 __ pop(edi); |
| 406 __ pop(esi); | 409 __ pop(esi); |
| 407 | 410 |
| 408 // Check if function returned non-zero for success or zero for failure. | 411 // Check if function returned non-zero for success or zero for failure. |
| 409 __ or_(eax, Operand(eax)); | 412 __ or_(eax, eax); |
| 410 BranchOrBacktrack(zero, on_no_match); | 413 BranchOrBacktrack(zero, on_no_match); |
| 411 // On success, increment position by length of capture. | 414 // On success, increment position by length of capture. |
| 412 __ add(edi, Operand(ebx)); | 415 __ add(edi, ebx); |
| 413 } | 416 } |
| 414 __ bind(&fallthrough); | 417 __ bind(&fallthrough); |
| 415 } | 418 } |
| 416 | 419 |
| 417 | 420 |
| 418 void RegExpMacroAssemblerIA32::CheckNotBackReference( | 421 void RegExpMacroAssemblerIA32::CheckNotBackReference( |
| 419 int start_reg, | 422 int start_reg, |
| 420 Label* on_no_match) { | 423 Label* on_no_match) { |
| 421 Label fallthrough; | 424 Label fallthrough; |
| 422 Label success; | 425 Label success; |
| 423 Label fail; | 426 Label fail; |
| 424 | 427 |
| 425 // Find length of back-referenced capture. | 428 // Find length of back-referenced capture. |
| 426 __ mov(edx, register_location(start_reg)); | 429 __ mov(edx, register_location(start_reg)); |
| 427 __ mov(eax, register_location(start_reg + 1)); | 430 __ mov(eax, register_location(start_reg + 1)); |
| 428 __ sub(eax, Operand(edx)); // Length to check. | 431 __ sub(eax, edx); // Length to check. |
| 429 // Fail on partial or illegal capture (start of capture after end of capture). | 432 // Fail on partial or illegal capture (start of capture after end of capture). |
| 430 BranchOrBacktrack(less, on_no_match); | 433 BranchOrBacktrack(less, on_no_match); |
| 431 // Succeed on empty capture (including no capture) | 434 // Succeed on empty capture (including no capture) |
| 432 __ j(equal, &fallthrough); | 435 __ j(equal, &fallthrough); |
| 433 | 436 |
| 434 // Check that there are sufficient characters left in the input. | 437 // Check that there are sufficient characters left in the input. |
| 435 __ mov(ebx, edi); | 438 __ mov(ebx, edi); |
| 436 __ add(ebx, Operand(eax)); | 439 __ add(ebx, eax); |
| 437 BranchOrBacktrack(greater, on_no_match); | 440 BranchOrBacktrack(greater, on_no_match); |
| 438 | 441 |
| 439 // Save register to make it available below. | 442 // Save register to make it available below. |
| 440 __ push(backtrack_stackpointer()); | 443 __ push(backtrack_stackpointer()); |
| 441 | 444 |
| 442 // Compute pointers to match string and capture string | 445 // Compute pointers to match string and capture string |
| 443 __ lea(ebx, Operand(esi, edi, times_1, 0)); // Start of match. | 446 __ lea(ebx, Operand(esi, edi, times_1, 0)); // Start of match. |
| 444 __ add(edx, Operand(esi)); // Start of capture. | 447 __ add(edx, esi); // Start of capture. |
| 445 __ lea(ecx, Operand(eax, ebx, times_1, 0)); // End of match | 448 __ lea(ecx, Operand(eax, ebx, times_1, 0)); // End of match |
| 446 | 449 |
| 447 Label loop; | 450 Label loop; |
| 448 __ bind(&loop); | 451 __ bind(&loop); |
| 449 if (mode_ == ASCII) { | 452 if (mode_ == ASCII) { |
| 450 __ movzx_b(eax, Operand(edx, 0)); | 453 __ movzx_b(eax, Operand(edx, 0)); |
| 451 __ cmpb_al(Operand(ebx, 0)); | 454 __ cmpb_al(Operand(ebx, 0)); |
| 452 } else { | 455 } else { |
| 453 ASSERT(mode_ == UC16); | 456 ASSERT(mode_ == UC16); |
| 454 __ movzx_w(eax, Operand(edx, 0)); | 457 __ movzx_w(eax, Operand(edx, 0)); |
| 455 __ cmpw_ax(Operand(ebx, 0)); | 458 __ cmpw_ax(Operand(ebx, 0)); |
| 456 } | 459 } |
| 457 __ j(not_equal, &fail); | 460 __ j(not_equal, &fail); |
| 458 // Increment pointers into capture and match string. | 461 // Increment pointers into capture and match string. |
| 459 __ add(Operand(edx), Immediate(char_size())); | 462 __ add(edx, Immediate(char_size())); |
| 460 __ add(Operand(ebx), Immediate(char_size())); | 463 __ add(ebx, Immediate(char_size())); |
| 461 // Check if we have reached end of match area. | 464 // Check if we have reached end of match area. |
| 462 __ cmp(ebx, Operand(ecx)); | 465 __ cmp(ebx, ecx); |
| 463 __ j(below, &loop); | 466 __ j(below, &loop); |
| 464 __ jmp(&success); | 467 __ jmp(&success); |
| 465 | 468 |
| 466 __ bind(&fail); | 469 __ bind(&fail); |
| 467 // Restore backtrack stackpointer. | 470 // Restore backtrack stackpointer. |
| 468 __ pop(backtrack_stackpointer()); | 471 __ pop(backtrack_stackpointer()); |
| 469 BranchOrBacktrack(no_condition, on_no_match); | 472 BranchOrBacktrack(no_condition, on_no_match); |
| 470 | 473 |
| 471 __ bind(&success); | 474 __ bind(&success); |
| 472 // Move current character position to position after match. | 475 // Move current character position to position after match. |
| 473 __ mov(edi, ecx); | 476 __ mov(edi, ecx); |
| 474 __ sub(Operand(edi), esi); | 477 __ sub(edi, esi); |
| 475 // Restore backtrack stackpointer. | 478 // Restore backtrack stackpointer. |
| 476 __ pop(backtrack_stackpointer()); | 479 __ pop(backtrack_stackpointer()); |
| 477 | 480 |
| 478 __ bind(&fallthrough); | 481 __ bind(&fallthrough); |
| 479 } | 482 } |
| 480 | 483 |
| 481 | 484 |
| 482 void RegExpMacroAssemblerIA32::CheckNotRegistersEqual(int reg1, | 485 void RegExpMacroAssemblerIA32::CheckNotRegistersEqual(int reg1, |
| 483 int reg2, | 486 int reg2, |
| 484 Label* on_not_equal) { | 487 Label* on_not_equal) { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 567 BranchOrBacktrack(above, on_no_match); | 570 BranchOrBacktrack(above, on_no_match); |
| 568 return true; | 571 return true; |
| 569 case 'D': | 572 case 'D': |
| 570 // Match non ASCII-digits | 573 // Match non ASCII-digits |
| 571 __ lea(eax, Operand(current_character(), -'0')); | 574 __ lea(eax, Operand(current_character(), -'0')); |
| 572 __ cmp(eax, '9' - '0'); | 575 __ cmp(eax, '9' - '0'); |
| 573 BranchOrBacktrack(below_equal, on_no_match); | 576 BranchOrBacktrack(below_equal, on_no_match); |
| 574 return true; | 577 return true; |
| 575 case '.': { | 578 case '.': { |
| 576 // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029) | 579 // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029) |
| 577 __ mov(Operand(eax), current_character()); | 580 __ mov(eax, current_character()); |
| 578 __ xor_(Operand(eax), Immediate(0x01)); | 581 __ xor_(eax, Immediate(0x01)); |
| 579 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c | 582 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c |
| 580 __ sub(Operand(eax), Immediate(0x0b)); | 583 __ sub(eax, Immediate(0x0b)); |
| 581 __ cmp(eax, 0x0c - 0x0b); | 584 __ cmp(eax, 0x0c - 0x0b); |
| 582 BranchOrBacktrack(below_equal, on_no_match); | 585 BranchOrBacktrack(below_equal, on_no_match); |
| 583 if (mode_ == UC16) { | 586 if (mode_ == UC16) { |
| 584 // Compare original value to 0x2028 and 0x2029, using the already | 587 // Compare original value to 0x2028 and 0x2029, using the already |
| 585 // computed (current_char ^ 0x01 - 0x0b). I.e., check for | 588 // computed (current_char ^ 0x01 - 0x0b). I.e., check for |
| 586 // 0x201d (0x2028 - 0x0b) or 0x201e. | 589 // 0x201d (0x2028 - 0x0b) or 0x201e. |
| 587 __ sub(Operand(eax), Immediate(0x2028 - 0x0b)); | 590 __ sub(eax, Immediate(0x2028 - 0x0b)); |
| 588 __ cmp(eax, 0x2029 - 0x2028); | 591 __ cmp(eax, 0x2029 - 0x2028); |
| 589 BranchOrBacktrack(below_equal, on_no_match); | 592 BranchOrBacktrack(below_equal, on_no_match); |
| 590 } | 593 } |
| 591 return true; | 594 return true; |
| 592 } | 595 } |
| 593 case 'w': { | 596 case 'w': { |
| 594 if (mode_ != ASCII) { | 597 if (mode_ != ASCII) { |
| 595 // Table is 128 entries, so all ASCII characters can be tested. | 598 // Table is 128 entries, so all ASCII characters can be tested. |
| 596 __ cmp(Operand(current_character()), Immediate('z')); | 599 __ cmp(current_character(), Immediate('z')); |
| 597 BranchOrBacktrack(above, on_no_match); | 600 BranchOrBacktrack(above, on_no_match); |
| 598 } | 601 } |
| 599 ASSERT_EQ(0, word_character_map[0]); // Character '\0' is not a word char. | 602 ASSERT_EQ(0, word_character_map[0]); // Character '\0' is not a word char. |
| 600 ExternalReference word_map = ExternalReference::re_word_character_map(); | 603 ExternalReference word_map = ExternalReference::re_word_character_map(); |
| 601 __ test_b(current_character(), | 604 __ test_b(current_character(), |
| 602 Operand::StaticArray(current_character(), times_1, word_map)); | 605 Operand::StaticArray(current_character(), times_1, word_map)); |
| 603 BranchOrBacktrack(zero, on_no_match); | 606 BranchOrBacktrack(zero, on_no_match); |
| 604 return true; | 607 return true; |
| 605 } | 608 } |
| 606 case 'W': { | 609 case 'W': { |
| 607 Label done; | 610 Label done; |
| 608 if (mode_ != ASCII) { | 611 if (mode_ != ASCII) { |
| 609 // Table is 128 entries, so all ASCII characters can be tested. | 612 // Table is 128 entries, so all ASCII characters can be tested. |
| 610 __ cmp(Operand(current_character()), Immediate('z')); | 613 __ cmp(current_character(), Immediate('z')); |
| 611 __ j(above, &done); | 614 __ j(above, &done); |
| 612 } | 615 } |
| 613 ASSERT_EQ(0, word_character_map[0]); // Character '\0' is not a word char. | 616 ASSERT_EQ(0, word_character_map[0]); // Character '\0' is not a word char. |
| 614 ExternalReference word_map = ExternalReference::re_word_character_map(); | 617 ExternalReference word_map = ExternalReference::re_word_character_map(); |
| 615 __ test_b(current_character(), | 618 __ test_b(current_character(), |
| 616 Operand::StaticArray(current_character(), times_1, word_map)); | 619 Operand::StaticArray(current_character(), times_1, word_map)); |
| 617 BranchOrBacktrack(not_zero, on_no_match); | 620 BranchOrBacktrack(not_zero, on_no_match); |
| 618 if (mode_ != ASCII) { | 621 if (mode_ != ASCII) { |
| 619 __ bind(&done); | 622 __ bind(&done); |
| 620 } | 623 } |
| 621 return true; | 624 return true; |
| 622 } | 625 } |
| 623 // Non-standard classes (with no syntactic shorthand) used internally. | 626 // Non-standard classes (with no syntactic shorthand) used internally. |
| 624 case '*': | 627 case '*': |
| 625 // Match any character. | 628 // Match any character. |
| 626 return true; | 629 return true; |
| 627 case 'n': { | 630 case 'n': { |
| 628 // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 or 0x2029). | 631 // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 or 0x2029). |
| 629 // The opposite of '.'. | 632 // The opposite of '.'. |
| 630 __ mov(Operand(eax), current_character()); | 633 __ mov(eax, current_character()); |
| 631 __ xor_(Operand(eax), Immediate(0x01)); | 634 __ xor_(eax, Immediate(0x01)); |
| 632 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c | 635 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c |
| 633 __ sub(Operand(eax), Immediate(0x0b)); | 636 __ sub(eax, Immediate(0x0b)); |
| 634 __ cmp(eax, 0x0c - 0x0b); | 637 __ cmp(eax, 0x0c - 0x0b); |
| 635 if (mode_ == ASCII) { | 638 if (mode_ == ASCII) { |
| 636 BranchOrBacktrack(above, on_no_match); | 639 BranchOrBacktrack(above, on_no_match); |
| 637 } else { | 640 } else { |
| 638 Label done; | 641 Label done; |
| 639 BranchOrBacktrack(below_equal, &done); | 642 BranchOrBacktrack(below_equal, &done); |
| 640 ASSERT_EQ(UC16, mode_); | 643 ASSERT_EQ(UC16, mode_); |
| 641 // Compare original value to 0x2028 and 0x2029, using the already | 644 // Compare original value to 0x2028 and 0x2029, using the already |
| 642 // computed (current_char ^ 0x01 - 0x0b). I.e., check for | 645 // computed (current_char ^ 0x01 - 0x0b). I.e., check for |
| 643 // 0x201d (0x2028 - 0x0b) or 0x201e. | 646 // 0x201d (0x2028 - 0x0b) or 0x201e. |
| 644 __ sub(Operand(eax), Immediate(0x2028 - 0x0b)); | 647 __ sub(eax, Immediate(0x2028 - 0x0b)); |
| 645 __ cmp(eax, 1); | 648 __ cmp(eax, 1); |
| 646 BranchOrBacktrack(above, on_no_match); | 649 BranchOrBacktrack(above, on_no_match); |
| 647 __ bind(&done); | 650 __ bind(&done); |
| 648 } | 651 } |
| 649 return true; | 652 return true; |
| 650 } | 653 } |
| 651 // No custom implementation (yet): s(UC16), S(UC16). | 654 // No custom implementation (yet): s(UC16), S(UC16). |
| 652 default: | 655 default: |
| 653 return false; | 656 return false; |
| 654 } | 657 } |
| 655 } | 658 } |
| 656 | 659 |
| 657 | 660 |
| 658 void RegExpMacroAssemblerIA32::Fail() { | 661 void RegExpMacroAssemblerIA32::Fail() { |
| 659 ASSERT(FAILURE == 0); // Return value for failure is zero. | 662 ASSERT(FAILURE == 0); // Return value for failure is zero. |
| 660 __ Set(eax, Immediate(0)); | 663 __ Set(eax, Immediate(0)); |
| 661 __ jmp(&exit_label_); | 664 __ jmp(&exit_label_); |
| 662 } | 665 } |
| 663 | 666 |
| 664 | 667 |
| 665 Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) { | 668 Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) { |
| 666 // Finalize code - write the entry point code now we know how many | 669 // Finalize code - write the entry point code now we know how many |
| 667 // registers we need. | 670 // registers we need. |
| 668 | 671 |
| 669 // Entry code: | 672 // Entry code: |
| 670 __ bind(&entry_label_); | 673 __ bind(&entry_label_); |
| 671 // Start new stack frame. | 674 |
| 675 // Tell the system that we have a stack frame. Because the type is MANUAL, no |
| 676 // code is generated. |
| 677 FrameScope scope(masm_, StackFrame::MANUAL); |
| 678 |
| 679 // Actually emit code to start a new stack frame. |
| 672 __ push(ebp); | 680 __ push(ebp); |
| 673 __ mov(ebp, esp); | 681 __ mov(ebp, esp); |
| 674 // Save callee-save registers. Order here should correspond to order of | 682 // Save callee-save registers. Order here should correspond to order of |
| 675 // kBackup_ebx etc. | 683 // kBackup_ebx etc. |
| 676 __ push(esi); | 684 __ push(esi); |
| 677 __ push(edi); | 685 __ push(edi); |
| 678 __ push(ebx); // Callee-save on MacOS. | 686 __ push(ebx); // Callee-save on MacOS. |
| 679 __ push(Immediate(0)); // Make room for "input start - 1" constant. | 687 __ push(Immediate(0)); // Make room for "input start - 1" constant. |
| 680 | 688 |
| 681 // Check if we have space on the stack for registers. | 689 // Check if we have space on the stack for registers. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 692 // the stack limit. | 700 // the stack limit. |
| 693 __ cmp(ecx, num_registers_ * kPointerSize); | 701 __ cmp(ecx, num_registers_ * kPointerSize); |
| 694 __ j(above_equal, &stack_ok); | 702 __ j(above_equal, &stack_ok); |
| 695 // Exit with OutOfMemory exception. There is not enough space on the stack | 703 // Exit with OutOfMemory exception. There is not enough space on the stack |
| 696 // for our working registers. | 704 // for our working registers. |
| 697 __ mov(eax, EXCEPTION); | 705 __ mov(eax, EXCEPTION); |
| 698 __ jmp(&exit_label_); | 706 __ jmp(&exit_label_); |
| 699 | 707 |
| 700 __ bind(&stack_limit_hit); | 708 __ bind(&stack_limit_hit); |
| 701 CallCheckStackGuardState(ebx); | 709 CallCheckStackGuardState(ebx); |
| 702 __ or_(eax, Operand(eax)); | 710 __ or_(eax, eax); |
| 703 // If returned value is non-zero, we exit with the returned value as result. | 711 // If returned value is non-zero, we exit with the returned value as result. |
| 704 __ j(not_zero, &exit_label_); | 712 __ j(not_zero, &exit_label_); |
| 705 | 713 |
| 706 __ bind(&stack_ok); | 714 __ bind(&stack_ok); |
| 707 // Load start index for later use. | 715 // Load start index for later use. |
| 708 __ mov(ebx, Operand(ebp, kStartIndex)); | 716 __ mov(ebx, Operand(ebp, kStartIndex)); |
| 709 | 717 |
| 710 // Allocate space on stack for registers. | 718 // Allocate space on stack for registers. |
| 711 __ sub(Operand(esp), Immediate(num_registers_ * kPointerSize)); | 719 __ sub(esp, Immediate(num_registers_ * kPointerSize)); |
| 712 // Load string length. | 720 // Load string length. |
| 713 __ mov(esi, Operand(ebp, kInputEnd)); | 721 __ mov(esi, Operand(ebp, kInputEnd)); |
| 714 // Load input position. | 722 // Load input position. |
| 715 __ mov(edi, Operand(ebp, kInputStart)); | 723 __ mov(edi, Operand(ebp, kInputStart)); |
| 716 // Set up edi to be negative offset from string end. | 724 // Set up edi to be negative offset from string end. |
| 717 __ sub(edi, Operand(esi)); | 725 __ sub(edi, esi); |
| 718 | 726 |
| 719 // Set eax to address of char before start of the string. | 727 // Set eax to address of char before start of the string. |
| 720 // (effectively string position -1). | 728 // (effectively string position -1). |
| 721 __ neg(ebx); | 729 __ neg(ebx); |
| 722 if (mode_ == UC16) { | 730 if (mode_ == UC16) { |
| 723 __ lea(eax, Operand(edi, ebx, times_2, -char_size())); | 731 __ lea(eax, Operand(edi, ebx, times_2, -char_size())); |
| 724 } else { | 732 } else { |
| 725 __ lea(eax, Operand(edi, ebx, times_1, -char_size())); | 733 __ lea(eax, Operand(edi, ebx, times_1, -char_size())); |
| 726 } | 734 } |
| 727 // Store this value in a local variable, for use when clearing | 735 // Store this value in a local variable, for use when clearing |
| 728 // position registers. | 736 // position registers. |
| 729 __ mov(Operand(ebp, kInputStartMinusOne), eax); | 737 __ mov(Operand(ebp, kInputStartMinusOne), eax); |
| 730 | 738 |
| 731 if (num_saved_registers_ > 0) { // Always is, if generated from a regexp. | 739 if (num_saved_registers_ > 0) { // Always is, if generated from a regexp. |
| 732 // Fill saved registers with initial value = start offset - 1 | 740 // Fill saved registers with initial value = start offset - 1 |
| 733 // Fill in stack push order, to avoid accessing across an unwritten | 741 // Fill in stack push order, to avoid accessing across an unwritten |
| 734 // page (a problem on Windows). | 742 // page (a problem on Windows). |
| 735 __ mov(ecx, kRegisterZero); | 743 __ mov(ecx, kRegisterZero); |
| 736 Label init_loop; | 744 Label init_loop; |
| 737 __ bind(&init_loop); | 745 __ bind(&init_loop); |
| 738 __ mov(Operand(ebp, ecx, times_1, +0), eax); | 746 __ mov(Operand(ebp, ecx, times_1, +0), eax); |
| 739 __ sub(Operand(ecx), Immediate(kPointerSize)); | 747 __ sub(ecx, Immediate(kPointerSize)); |
| 740 __ cmp(ecx, kRegisterZero - num_saved_registers_ * kPointerSize); | 748 __ cmp(ecx, kRegisterZero - num_saved_registers_ * kPointerSize); |
| 741 __ j(greater, &init_loop); | 749 __ j(greater, &init_loop); |
| 742 } | 750 } |
| 743 // Ensure that we have written to each stack page, in order. Skipping a page | 751 // Ensure that we have written to each stack page, in order. Skipping a page |
| 744 // on Windows can cause segmentation faults. Assuming page size is 4k. | 752 // on Windows can cause segmentation faults. Assuming page size is 4k. |
| 745 const int kPageSize = 4096; | 753 const int kPageSize = 4096; |
| 746 const int kRegistersPerPage = kPageSize / kPointerSize; | 754 const int kRegistersPerPage = kPageSize / kPointerSize; |
| 747 for (int i = num_saved_registers_ + kRegistersPerPage - 1; | 755 for (int i = num_saved_registers_ + kRegistersPerPage - 1; |
| 748 i < num_registers_; | 756 i < num_registers_; |
| 749 i += kRegistersPerPage) { | 757 i += kRegistersPerPage) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 770 __ bind(&success_label_); | 778 __ bind(&success_label_); |
| 771 if (num_saved_registers_ > 0) { | 779 if (num_saved_registers_ > 0) { |
| 772 // copy captures to output | 780 // copy captures to output |
| 773 __ mov(ebx, Operand(ebp, kRegisterOutput)); | 781 __ mov(ebx, Operand(ebp, kRegisterOutput)); |
| 774 __ mov(ecx, Operand(ebp, kInputEnd)); | 782 __ mov(ecx, Operand(ebp, kInputEnd)); |
| 775 __ mov(edx, Operand(ebp, kStartIndex)); | 783 __ mov(edx, Operand(ebp, kStartIndex)); |
| 776 __ sub(ecx, Operand(ebp, kInputStart)); | 784 __ sub(ecx, Operand(ebp, kInputStart)); |
| 777 if (mode_ == UC16) { | 785 if (mode_ == UC16) { |
| 778 __ lea(ecx, Operand(ecx, edx, times_2, 0)); | 786 __ lea(ecx, Operand(ecx, edx, times_2, 0)); |
| 779 } else { | 787 } else { |
| 780 __ add(ecx, Operand(edx)); | 788 __ add(ecx, edx); |
| 781 } | 789 } |
| 782 for (int i = 0; i < num_saved_registers_; i++) { | 790 for (int i = 0; i < num_saved_registers_; i++) { |
| 783 __ mov(eax, register_location(i)); | 791 __ mov(eax, register_location(i)); |
| 784 // Convert to index from start of string, not end. | 792 // Convert to index from start of string, not end. |
| 785 __ add(eax, Operand(ecx)); | 793 __ add(eax, ecx); |
| 786 if (mode_ == UC16) { | 794 if (mode_ == UC16) { |
| 787 __ sar(eax, 1); // Convert byte index to character index. | 795 __ sar(eax, 1); // Convert byte index to character index. |
| 788 } | 796 } |
| 789 __ mov(Operand(ebx, i * kPointerSize), eax); | 797 __ mov(Operand(ebx, i * kPointerSize), eax); |
| 790 } | 798 } |
| 791 } | 799 } |
| 792 __ mov(eax, Immediate(SUCCESS)); | 800 __ mov(eax, Immediate(SUCCESS)); |
| 793 } | 801 } |
| 794 // Exit and return eax | 802 // Exit and return eax |
| 795 __ bind(&exit_label_); | 803 __ bind(&exit_label_); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 812 Label exit_with_exception; | 820 Label exit_with_exception; |
| 813 | 821 |
| 814 // Preempt-code | 822 // Preempt-code |
| 815 if (check_preempt_label_.is_linked()) { | 823 if (check_preempt_label_.is_linked()) { |
| 816 SafeCallTarget(&check_preempt_label_); | 824 SafeCallTarget(&check_preempt_label_); |
| 817 | 825 |
| 818 __ push(backtrack_stackpointer()); | 826 __ push(backtrack_stackpointer()); |
| 819 __ push(edi); | 827 __ push(edi); |
| 820 | 828 |
| 821 CallCheckStackGuardState(ebx); | 829 CallCheckStackGuardState(ebx); |
| 822 __ or_(eax, Operand(eax)); | 830 __ or_(eax, eax); |
| 823 // If returning non-zero, we should end execution with the given | 831 // If returning non-zero, we should end execution with the given |
| 824 // result as return value. | 832 // result as return value. |
| 825 __ j(not_zero, &exit_label_); | 833 __ j(not_zero, &exit_label_); |
| 826 | 834 |
| 827 __ pop(edi); | 835 __ pop(edi); |
| 828 __ pop(backtrack_stackpointer()); | 836 __ pop(backtrack_stackpointer()); |
| 829 // String might have moved: Reload esi from frame. | 837 // String might have moved: Reload esi from frame. |
| 830 __ mov(esi, Operand(ebp, kInputEnd)); | 838 __ mov(esi, Operand(ebp, kInputEnd)); |
| 831 SafeReturn(); | 839 SafeReturn(); |
| 832 } | 840 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 847 __ mov(Operand(esp, 2 * kPointerSize), | 855 __ mov(Operand(esp, 2 * kPointerSize), |
| 848 Immediate(ExternalReference::isolate_address())); | 856 Immediate(ExternalReference::isolate_address())); |
| 849 __ lea(eax, Operand(ebp, kStackHighEnd)); | 857 __ lea(eax, Operand(ebp, kStackHighEnd)); |
| 850 __ mov(Operand(esp, 1 * kPointerSize), eax); | 858 __ mov(Operand(esp, 1 * kPointerSize), eax); |
| 851 __ mov(Operand(esp, 0 * kPointerSize), backtrack_stackpointer()); | 859 __ mov(Operand(esp, 0 * kPointerSize), backtrack_stackpointer()); |
| 852 ExternalReference grow_stack = | 860 ExternalReference grow_stack = |
| 853 ExternalReference::re_grow_stack(masm_->isolate()); | 861 ExternalReference::re_grow_stack(masm_->isolate()); |
| 854 __ CallCFunction(grow_stack, num_arguments); | 862 __ CallCFunction(grow_stack, num_arguments); |
| 855 // If return NULL, we have failed to grow the stack, and | 863 // If return NULL, we have failed to grow the stack, and |
| 856 // must exit with a stack-overflow exception. | 864 // must exit with a stack-overflow exception. |
| 857 __ or_(eax, Operand(eax)); | 865 __ or_(eax, eax); |
| 858 __ j(equal, &exit_with_exception); | 866 __ j(equal, &exit_with_exception); |
| 859 // Otherwise use return value as new stack pointer. | 867 // Otherwise use return value as new stack pointer. |
| 860 __ mov(backtrack_stackpointer(), eax); | 868 __ mov(backtrack_stackpointer(), eax); |
| 861 // Restore saved registers and continue. | 869 // Restore saved registers and continue. |
| 862 __ pop(edi); | 870 __ pop(edi); |
| 863 __ pop(esi); | 871 __ pop(esi); |
| 864 SafeReturn(); | 872 SafeReturn(); |
| 865 } | 873 } |
| 866 | 874 |
| 867 if (exit_with_exception.is_linked()) { | 875 if (exit_with_exception.is_linked()) { |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1176 void RegExpMacroAssemblerIA32::SafeCall(Label* to) { | 1184 void RegExpMacroAssemblerIA32::SafeCall(Label* to) { |
| 1177 Label return_to; | 1185 Label return_to; |
| 1178 __ push(Immediate::CodeRelativeOffset(&return_to)); | 1186 __ push(Immediate::CodeRelativeOffset(&return_to)); |
| 1179 __ jmp(to); | 1187 __ jmp(to); |
| 1180 __ bind(&return_to); | 1188 __ bind(&return_to); |
| 1181 } | 1189 } |
| 1182 | 1190 |
| 1183 | 1191 |
| 1184 void RegExpMacroAssemblerIA32::SafeReturn() { | 1192 void RegExpMacroAssemblerIA32::SafeReturn() { |
| 1185 __ pop(ebx); | 1193 __ pop(ebx); |
| 1186 __ add(Operand(ebx), Immediate(masm_->CodeObject())); | 1194 __ add(ebx, Immediate(masm_->CodeObject())); |
| 1187 __ jmp(Operand(ebx)); | 1195 __ jmp(ebx); |
| 1188 } | 1196 } |
| 1189 | 1197 |
| 1190 | 1198 |
| 1191 void RegExpMacroAssemblerIA32::SafeCallTarget(Label* name) { | 1199 void RegExpMacroAssemblerIA32::SafeCallTarget(Label* name) { |
| 1192 __ bind(name); | 1200 __ bind(name); |
| 1193 } | 1201 } |
| 1194 | 1202 |
| 1195 | 1203 |
| 1196 void RegExpMacroAssemblerIA32::Push(Register source) { | 1204 void RegExpMacroAssemblerIA32::Push(Register source) { |
| 1197 ASSERT(!source.is(backtrack_stackpointer())); | 1205 ASSERT(!source.is(backtrack_stackpointer())); |
| 1198 // Notice: This updates flags, unlike normal Push. | 1206 // Notice: This updates flags, unlike normal Push. |
| 1199 __ sub(Operand(backtrack_stackpointer()), Immediate(kPointerSize)); | 1207 __ sub(backtrack_stackpointer(), Immediate(kPointerSize)); |
| 1200 __ mov(Operand(backtrack_stackpointer(), 0), source); | 1208 __ mov(Operand(backtrack_stackpointer(), 0), source); |
| 1201 } | 1209 } |
| 1202 | 1210 |
| 1203 | 1211 |
| 1204 void RegExpMacroAssemblerIA32::Push(Immediate value) { | 1212 void RegExpMacroAssemblerIA32::Push(Immediate value) { |
| 1205 // Notice: This updates flags, unlike normal Push. | 1213 // Notice: This updates flags, unlike normal Push. |
| 1206 __ sub(Operand(backtrack_stackpointer()), Immediate(kPointerSize)); | 1214 __ sub(backtrack_stackpointer(), Immediate(kPointerSize)); |
| 1207 __ mov(Operand(backtrack_stackpointer(), 0), value); | 1215 __ mov(Operand(backtrack_stackpointer(), 0), value); |
| 1208 } | 1216 } |
| 1209 | 1217 |
| 1210 | 1218 |
| 1211 void RegExpMacroAssemblerIA32::Pop(Register target) { | 1219 void RegExpMacroAssemblerIA32::Pop(Register target) { |
| 1212 ASSERT(!target.is(backtrack_stackpointer())); | 1220 ASSERT(!target.is(backtrack_stackpointer())); |
| 1213 __ mov(target, Operand(backtrack_stackpointer(), 0)); | 1221 __ mov(target, Operand(backtrack_stackpointer(), 0)); |
| 1214 // Notice: This updates flags, unlike normal Pop. | 1222 // Notice: This updates flags, unlike normal Pop. |
| 1215 __ add(Operand(backtrack_stackpointer()), Immediate(kPointerSize)); | 1223 __ add(backtrack_stackpointer(), Immediate(kPointerSize)); |
| 1216 } | 1224 } |
| 1217 | 1225 |
| 1218 | 1226 |
| 1219 void RegExpMacroAssemblerIA32::CheckPreemption() { | 1227 void RegExpMacroAssemblerIA32::CheckPreemption() { |
| 1220 // Check for preemption. | 1228 // Check for preemption. |
| 1221 Label no_preempt; | 1229 Label no_preempt; |
| 1222 ExternalReference stack_limit = | 1230 ExternalReference stack_limit = |
| 1223 ExternalReference::address_of_stack_limit(masm_->isolate()); | 1231 ExternalReference::address_of_stack_limit(masm_->isolate()); |
| 1224 __ cmp(esp, Operand::StaticVariable(stack_limit)); | 1232 __ cmp(esp, Operand::StaticVariable(stack_limit)); |
| 1225 __ j(above, &no_preempt); | 1233 __ j(above, &no_preempt); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1268 } | 1276 } |
| 1269 | 1277 |
| 1270 | 1278 |
| 1271 #undef __ | 1279 #undef __ |
| 1272 | 1280 |
| 1273 #endif // V8_INTERPRETED_REGEXP | 1281 #endif // V8_INTERPRETED_REGEXP |
| 1274 | 1282 |
| 1275 }} // namespace v8::internal | 1283 }} // namespace v8::internal |
| 1276 | 1284 |
| 1277 #endif // V8_TARGET_ARCH_IA32 | 1285 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |