| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 * int start_index, | 108 * int start_index, |
| 109 * Address start, | 109 * Address start, |
| 110 * Address end, | 110 * Address end, |
| 111 * int* capture_output_array, | 111 * int* capture_output_array, |
| 112 * bool at_start, | 112 * bool at_start, |
| 113 * byte* stack_area_base, | 113 * byte* stack_area_base, |
| 114 * bool direct_call) | 114 * bool direct_call) |
| 115 */ | 115 */ |
| 116 | 116 |
| 117 #define __ ACCESS_MASM((&masm_)) | 117 #define __ ACCESS_MASM((&masm_)) |
| 118 #define __k __ |
| 118 | 119 |
| 119 RegExpMacroAssemblerX64::RegExpMacroAssemblerX64( | 120 RegExpMacroAssemblerX64::RegExpMacroAssemblerX64( |
| 120 Mode mode, | 121 Mode mode, |
| 121 int registers_to_save, | 122 int registers_to_save, |
| 122 Zone* zone) | 123 Zone* zone) |
| 123 : NativeRegExpMacroAssembler(zone), | 124 : NativeRegExpMacroAssembler(zone), |
| 124 masm_(zone->isolate(), NULL, kRegExpCodeSize), | 125 masm_(zone->isolate(), NULL, kRegExpCodeSize), |
| 125 no_root_array_scope_(&masm_), | 126 no_root_array_scope_(&masm_), |
| 126 code_relative_fixup_positions_(4, zone), | 127 code_relative_fixup_positions_(4, zone), |
| 127 mode_(mode), | 128 mode_(mode), |
| (...skipping 22 matching lines...) Expand all Loading... |
| 150 } | 151 } |
| 151 | 152 |
| 152 | 153 |
| 153 int RegExpMacroAssemblerX64::stack_limit_slack() { | 154 int RegExpMacroAssemblerX64::stack_limit_slack() { |
| 154 return RegExpStack::kStackLimitSlack; | 155 return RegExpStack::kStackLimitSlack; |
| 155 } | 156 } |
| 156 | 157 |
| 157 | 158 |
| 158 void RegExpMacroAssemblerX64::AdvanceCurrentPosition(int by) { | 159 void RegExpMacroAssemblerX64::AdvanceCurrentPosition(int by) { |
| 159 if (by != 0) { | 160 if (by != 0) { |
| 160 __ addq(rdi, Immediate(by * char_size())); | 161 __k addq(rdi, Immediate(by * char_size())); |
| 161 } | 162 } |
| 162 } | 163 } |
| 163 | 164 |
| 164 | 165 |
| 165 void RegExpMacroAssemblerX64::AdvanceRegister(int reg, int by) { | 166 void RegExpMacroAssemblerX64::AdvanceRegister(int reg, int by) { |
| 166 ASSERT(reg >= 0); | 167 ASSERT(reg >= 0); |
| 167 ASSERT(reg < num_registers_); | 168 ASSERT(reg < num_registers_); |
| 168 if (by != 0) { | 169 if (by != 0) { |
| 169 __ addq(register_location(reg), Immediate(by)); | 170 __ addq(register_location(reg), Immediate(by)); |
| 170 } | 171 } |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 Drop(); | 235 Drop(); |
| 235 BranchOrBacktrack(no_condition, on_equal); | 236 BranchOrBacktrack(no_condition, on_equal); |
| 236 __ bind(&fallthrough); | 237 __ bind(&fallthrough); |
| 237 } | 238 } |
| 238 | 239 |
| 239 | 240 |
| 240 void RegExpMacroAssemblerX64::CheckNotBackReferenceIgnoreCase( | 241 void RegExpMacroAssemblerX64::CheckNotBackReferenceIgnoreCase( |
| 241 int start_reg, | 242 int start_reg, |
| 242 Label* on_no_match) { | 243 Label* on_no_match) { |
| 243 Label fallthrough; | 244 Label fallthrough; |
| 245 #ifndef V8_TARGET_ARCH_X32 |
| 244 __ movq(rdx, register_location(start_reg)); // Offset of start of capture | 246 __ movq(rdx, register_location(start_reg)); // Offset of start of capture |
| 245 __ movq(rbx, register_location(start_reg + 1)); // Offset of end of capture | 247 __ movq(rbx, register_location(start_reg + 1)); // Offset of end of capture |
| 248 #else |
| 249 __ movsxlq(rdx, register_location(start_reg)); // Offset of start of capture |
| 250 // Offset of end of capture |
| 251 __ movsxlq(rbx, register_location(start_reg + 1)); |
| 252 #endif |
| 246 __ subq(rbx, rdx); // Length of capture. | 253 __ subq(rbx, rdx); // Length of capture. |
| 247 | 254 |
| 248 // ----------------------- | 255 // ----------------------- |
| 249 // rdx = Start offset of capture. | 256 // rdx = Start offset of capture. |
| 250 // rbx = Length of capture | 257 // rbx = Length of capture |
| 251 | 258 |
| 252 // If length is negative, this code will fail (it's a symptom of a partial or | 259 // If length is negative, this code will fail (it's a symptom of a partial or |
| 253 // illegal capture where start of capture after end of capture). | 260 // illegal capture where start of capture after end of capture). |
| 254 // This must not happen (no back-reference can reference a capture that wasn't | 261 // This must not happen (no back-reference can reference a capture that wasn't |
| 255 // closed before in the reg-exp, and we must not generate code that can cause | 262 // closed before in the reg-exp, and we must not generate code that can cause |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 __ bind(&loop_increment); | 316 __ bind(&loop_increment); |
| 310 // Increment pointers into match and capture strings. | 317 // Increment pointers into match and capture strings. |
| 311 __ addq(r11, Immediate(1)); | 318 __ addq(r11, Immediate(1)); |
| 312 __ addq(r9, Immediate(1)); | 319 __ addq(r9, Immediate(1)); |
| 313 // Compare to end of capture, and loop if not done. | 320 // Compare to end of capture, and loop if not done. |
| 314 __ cmpq(r9, rbx); | 321 __ cmpq(r9, rbx); |
| 315 __ j(below, &loop); | 322 __ j(below, &loop); |
| 316 | 323 |
| 317 // Compute new value of character position after the matched part. | 324 // Compute new value of character position after the matched part. |
| 318 __ movq(rdi, r11); | 325 __ movq(rdi, r11); |
| 319 __ subq(rdi, rsi); | 326 __k subq(rdi, rsi); |
| 320 } else { | 327 } else { |
| 321 ASSERT(mode_ == UC16); | 328 ASSERT(mode_ == UC16); |
| 322 // Save important/volatile registers before calling C function. | 329 // Save important/volatile registers before calling C function. |
| 323 #ifndef _WIN64 | 330 #ifndef _WIN64 |
| 324 // Caller save on Linux and callee save in Windows. | 331 // Caller save on Linux and callee save in Windows. |
| 325 __ push(rsi); | 332 __k push(rsi); |
| 326 __ push(rdi); | 333 __k push(rdi); |
| 327 #endif | 334 #endif |
| 328 __ push(backtrack_stackpointer()); | 335 __k push(backtrack_stackpointer()); |
| 329 | 336 |
| 330 static const int num_arguments = 4; | 337 static const int num_arguments = 4; |
| 331 __ PrepareCallCFunction(num_arguments); | 338 __ PrepareCallCFunction(num_arguments); |
| 332 | 339 |
| 333 // Put arguments into parameter registers. Parameters are | 340 // Put arguments into parameter registers. Parameters are |
| 334 // Address byte_offset1 - Address captured substring's start. | 341 // Address byte_offset1 - Address captured substring's start. |
| 335 // Address byte_offset2 - Address of current character position. | 342 // Address byte_offset2 - Address of current character position. |
| 336 // size_t byte_length - length of capture in bytes(!) | 343 // size_t byte_length - length of capture in bytes(!) |
| 337 // Isolate* isolate | 344 // Isolate* isolate |
| 338 #ifdef _WIN64 | 345 #ifdef _WIN64 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 360 { // NOLINT: Can't find a way to open this scope without confusing the | 367 { // NOLINT: Can't find a way to open this scope without confusing the |
| 361 // linter. | 368 // linter. |
| 362 AllowExternalCallThatCantCauseGC scope(&masm_); | 369 AllowExternalCallThatCantCauseGC scope(&masm_); |
| 363 ExternalReference compare = | 370 ExternalReference compare = |
| 364 ExternalReference::re_case_insensitive_compare_uc16(isolate()); | 371 ExternalReference::re_case_insensitive_compare_uc16(isolate()); |
| 365 __ CallCFunction(compare, num_arguments); | 372 __ CallCFunction(compare, num_arguments); |
| 366 } | 373 } |
| 367 | 374 |
| 368 // Restore original values before reacting on result value. | 375 // Restore original values before reacting on result value. |
| 369 __ Move(code_object_pointer(), masm_.CodeObject()); | 376 __ Move(code_object_pointer(), masm_.CodeObject()); |
| 370 __ pop(backtrack_stackpointer()); | 377 __k pop(backtrack_stackpointer()); |
| 371 #ifndef _WIN64 | 378 #ifndef _WIN64 |
| 372 __ pop(rdi); | 379 __k pop(rdi); |
| 373 __ pop(rsi); | 380 __k pop(rsi); |
| 374 #endif | 381 #endif |
| 375 | 382 |
| 376 // Check if function returned non-zero for success or zero for failure. | 383 // Check if function returned non-zero for success or zero for failure. |
| 377 __ testq(rax, rax); | 384 __ testq(rax, rax); |
| 378 BranchOrBacktrack(zero, on_no_match); | 385 BranchOrBacktrack(zero, on_no_match); |
| 379 // On success, increment position by length of capture. | 386 // On success, increment position by length of capture. |
| 380 // Requires that rbx is callee save (true for both Win64 and AMD64 ABIs). | 387 // Requires that rbx is callee save (true for both Win64 and AMD64 ABIs). |
| 381 __ addq(rdi, rbx); | 388 __k addq(rdi, rbx); |
| 382 } | 389 } |
| 383 __ bind(&fallthrough); | 390 __ bind(&fallthrough); |
| 384 } | 391 } |
| 385 | 392 |
| 386 | 393 |
| 387 void RegExpMacroAssemblerX64::CheckNotBackReference( | 394 void RegExpMacroAssemblerX64::CheckNotBackReference( |
| 388 int start_reg, | 395 int start_reg, |
| 389 Label* on_no_match) { | 396 Label* on_no_match) { |
| 390 Label fallthrough; | 397 Label fallthrough; |
| 391 | 398 |
| 392 // Find length of back-referenced capture. | 399 // Find length of back-referenced capture. |
| 400 #ifndef V8_TARGET_ARCH_X32 |
| 393 __ movq(rdx, register_location(start_reg)); | 401 __ movq(rdx, register_location(start_reg)); |
| 394 __ movq(rax, register_location(start_reg + 1)); | 402 __ movq(rax, register_location(start_reg + 1)); |
| 403 #else |
| 404 __ movsxlq(rdx, register_location(start_reg)); |
| 405 __ movsxlq(rax, register_location(start_reg + 1)); |
| 406 #endif |
| 395 __ subq(rax, rdx); // Length to check. | 407 __ subq(rax, rdx); // Length to check. |
| 396 | 408 |
| 397 // Fail on partial or illegal capture (start of capture after end of capture). | 409 // Fail on partial or illegal capture (start of capture after end of capture). |
| 398 // This must not happen (no back-reference can reference a capture that wasn't | 410 // This must not happen (no back-reference can reference a capture that wasn't |
| 399 // closed before in the reg-exp). | 411 // closed before in the reg-exp). |
| 400 __ Check(greater_equal, "Invalid capture referenced"); | 412 __ Check(greater_equal, "Invalid capture referenced"); |
| 401 | 413 |
| 402 // Succeed on empty capture (including non-participating capture) | 414 // Succeed on empty capture (including non-participating capture) |
| 403 __ j(equal, &fallthrough); | 415 __ j(equal, &fallthrough); |
| 404 | 416 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 435 // Increment pointers into capture and match string. | 447 // Increment pointers into capture and match string. |
| 436 __ addq(rbx, Immediate(char_size())); | 448 __ addq(rbx, Immediate(char_size())); |
| 437 __ addq(rdx, Immediate(char_size())); | 449 __ addq(rdx, Immediate(char_size())); |
| 438 // Check if we have reached end of match area. | 450 // Check if we have reached end of match area. |
| 439 __ cmpq(rdx, r9); | 451 __ cmpq(rdx, r9); |
| 440 __ j(below, &loop); | 452 __ j(below, &loop); |
| 441 | 453 |
| 442 // Success. | 454 // Success. |
| 443 // Set current character position to position after match. | 455 // Set current character position to position after match. |
| 444 __ movq(rdi, rbx); | 456 __ movq(rdi, rbx); |
| 445 __ subq(rdi, rsi); | 457 __k subq(rdi, rsi); |
| 446 | 458 |
| 447 __ bind(&fallthrough); | 459 __ bind(&fallthrough); |
| 448 } | 460 } |
| 449 | 461 |
| 450 | 462 |
| 451 void RegExpMacroAssemblerX64::CheckNotCharacter(uint32_t c, | 463 void RegExpMacroAssemblerX64::CheckNotCharacter(uint32_t c, |
| 452 Label* on_not_equal) { | 464 Label* on_not_equal) { |
| 453 __ cmpl(current_character(), Immediate(c)); | 465 __ cmpl(current_character(), Immediate(c)); |
| 454 BranchOrBacktrack(not_equal, on_not_equal); | 466 BranchOrBacktrack(not_equal, on_not_equal); |
| 455 } | 467 } |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 674 FrameScope scope(&masm_, StackFrame::MANUAL); | 686 FrameScope scope(&masm_, StackFrame::MANUAL); |
| 675 | 687 |
| 676 // Actually emit code to start a new stack frame. | 688 // Actually emit code to start a new stack frame. |
| 677 __ push(rbp); | 689 __ push(rbp); |
| 678 __ movq(rbp, rsp); | 690 __ movq(rbp, rsp); |
| 679 // Save parameters and callee-save registers. Order here should correspond | 691 // Save parameters and callee-save registers. Order here should correspond |
| 680 // to order of kBackup_ebx etc. | 692 // to order of kBackup_ebx etc. |
| 681 #ifdef _WIN64 | 693 #ifdef _WIN64 |
| 682 // MSVC passes arguments in rcx, rdx, r8, r9, with backing stack slots. | 694 // MSVC passes arguments in rcx, rdx, r8, r9, with backing stack slots. |
| 683 // Store register parameters in pre-allocated stack slots, | 695 // Store register parameters in pre-allocated stack slots, |
| 684 __ movq(Operand(rbp, kInputString), rcx); | 696 __k movq(Operand(rbp, kInputString), rcx); |
| 685 __ movq(Operand(rbp, kStartIndex), rdx); // Passed as int32 in edx. | 697 __k movq(Operand(rbp, kStartIndex), rdx); // Passed as int32 in edx. |
| 686 __ movq(Operand(rbp, kInputStart), r8); | 698 __k movq(Operand(rbp, kInputStart), r8); |
| 687 __ movq(Operand(rbp, kInputEnd), r9); | 699 __k movq(Operand(rbp, kInputEnd), r9); |
| 688 // Callee-save on Win64. | 700 // Callee-save on Win64. |
| 689 __ push(rsi); | 701 __k push(rsi); |
| 690 __ push(rdi); | 702 __k push(rdi); |
| 691 __ push(rbx); | 703 __k push(rbx); |
| 692 #else | 704 #else |
| 693 // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9 (and then on stack). | 705 // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9 (and then on stack). |
| 694 // Push register parameters on stack for reference. | 706 // Push register parameters on stack for reference. |
| 707 #ifndef V8_TARGET_ARCH_X32 |
| 695 ASSERT_EQ(kInputString, -1 * kPointerSize); | 708 ASSERT_EQ(kInputString, -1 * kPointerSize); |
| 696 ASSERT_EQ(kStartIndex, -2 * kPointerSize); | 709 ASSERT_EQ(kStartIndex, -2 * kPointerSize); |
| 697 ASSERT_EQ(kInputStart, -3 * kPointerSize); | 710 ASSERT_EQ(kInputStart, -3 * kPointerSize); |
| 698 ASSERT_EQ(kInputEnd, -4 * kPointerSize); | 711 ASSERT_EQ(kInputEnd, -4 * kPointerSize); |
| 699 ASSERT_EQ(kRegisterOutput, -5 * kPointerSize); | 712 ASSERT_EQ(kRegisterOutput, -5 * kPointerSize); |
| 700 ASSERT_EQ(kNumOutputRegisters, -6 * kPointerSize); | 713 ASSERT_EQ(kNumOutputRegisters, -6 * kPointerSize); |
| 701 __ push(rdi); | 714 #else |
| 702 __ push(rsi); | 715 ASSERT_EQ(kInputString, -1 * kHWRegSize); |
| 703 __ push(rdx); | 716 ASSERT_EQ(kStartIndex, -2 * kHWRegSize); |
| 704 __ push(rcx); | 717 ASSERT_EQ(kInputStart, -3 * kHWRegSize); |
| 705 __ push(r8); | 718 ASSERT_EQ(kInputEnd, -4 * kHWRegSize); |
| 706 __ push(r9); | 719 ASSERT_EQ(kRegisterOutput, -5 * kHWRegSize); |
| 720 ASSERT_EQ(kNumOutputRegisters, -6 * kHWRegSize); |
| 721 #endif |
| 722 __k push(rdi); |
| 723 __k push(rsi); |
| 724 __k push(rdx); |
| 725 __k push(rcx); |
| 726 __k push(r8); |
| 727 __k push(r9); |
| 707 | 728 |
| 708 __ push(rbx); // Callee-save | 729 __k push(rbx); // Callee-save |
| 709 #endif | 730 #endif |
| 710 | 731 |
| 711 __ push(Immediate(0)); // Number of successful matches in a global regexp. | 732 __ push(Immediate(0)); // Number of successful matches in a global regexp. |
| 712 __ push(Immediate(0)); // Make room for "input start - 1" constant. | 733 __ push(Immediate(0)); // Make room for "input start - 1" constant. |
| 713 | 734 |
| 714 // Check if we have space on the stack for registers. | 735 // Check if we have space on the stack for registers. |
| 715 Label stack_limit_hit; | 736 Label stack_limit_hit; |
| 716 Label stack_ok; | 737 Label stack_ok; |
| 717 | 738 |
| 718 ExternalReference stack_limit = | 739 ExternalReference stack_limit = |
| (...skipping 21 matching lines...) Expand all Loading... |
| 740 | 761 |
| 741 __ bind(&stack_ok); | 762 __ bind(&stack_ok); |
| 742 | 763 |
| 743 // Allocate space on stack for registers. | 764 // Allocate space on stack for registers. |
| 744 __ subq(rsp, Immediate(num_registers_ * kPointerSize)); | 765 __ subq(rsp, Immediate(num_registers_ * kPointerSize)); |
| 745 // Load string length. | 766 // Load string length. |
| 746 __ movq(rsi, Operand(rbp, kInputEnd)); | 767 __ movq(rsi, Operand(rbp, kInputEnd)); |
| 747 // Load input position. | 768 // Load input position. |
| 748 __ movq(rdi, Operand(rbp, kInputStart)); | 769 __ movq(rdi, Operand(rbp, kInputStart)); |
| 749 // Set up rdi to be negative offset from string end. | 770 // Set up rdi to be negative offset from string end. |
| 750 __ subq(rdi, rsi); | 771 __k subq(rdi, rsi); |
| 751 // Set rax to address of char before start of the string | 772 // Set rax to address of char before start of the string |
| 752 // (effectively string position -1). | 773 // (effectively string position -1). |
| 753 __ movq(rbx, Operand(rbp, kStartIndex)); | 774 __ movq(rbx, Operand(rbp, kStartIndex)); |
| 754 __ neg(rbx); | 775 __k neg(rbx); |
| 755 if (mode_ == UC16) { | 776 if (mode_ == UC16) { |
| 756 __ lea(rax, Operand(rdi, rbx, times_2, -char_size())); | 777 __ lea(rax, Operand(rdi, rbx, times_2, -char_size())); |
| 757 } else { | 778 } else { |
| 758 __ lea(rax, Operand(rdi, rbx, times_1, -char_size())); | 779 __ lea(rax, Operand(rdi, rbx, times_1, -char_size())); |
| 759 } | 780 } |
| 760 // Store this value in a local variable, for use when clearing | 781 // Store this value in a local variable, for use when clearing |
| 761 // position registers. | 782 // position registers. |
| 762 __ movq(Operand(rbp, kInputStartMinusOne), rax); | 783 __ movq(Operand(rbp, kInputStartMinusOne), rax); |
| 763 | 784 |
| 764 #ifdef WIN32 | 785 #ifdef WIN32 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 792 // Initialize on-stack registers. | 813 // Initialize on-stack registers. |
| 793 if (num_saved_registers_ > 0) { | 814 if (num_saved_registers_ > 0) { |
| 794 // Fill saved registers with initial value = start offset - 1 | 815 // Fill saved registers with initial value = start offset - 1 |
| 795 // Fill in stack push order, to avoid accessing across an unwritten | 816 // Fill in stack push order, to avoid accessing across an unwritten |
| 796 // page (a problem on Windows). | 817 // page (a problem on Windows). |
| 797 if (num_saved_registers_ > 8) { | 818 if (num_saved_registers_ > 8) { |
| 798 __ Set(rcx, kRegisterZero); | 819 __ Set(rcx, kRegisterZero); |
| 799 Label init_loop; | 820 Label init_loop; |
| 800 __ bind(&init_loop); | 821 __ bind(&init_loop); |
| 801 __ movq(Operand(rbp, rcx, times_1, 0), rax); | 822 __ movq(Operand(rbp, rcx, times_1, 0), rax); |
| 802 __ subq(rcx, Immediate(kPointerSize)); | 823 __k subq(rcx, Immediate(kPointerSize)); |
| 803 __ cmpq(rcx, | 824 __k cmpq(rcx, |
| 804 Immediate(kRegisterZero - num_saved_registers_ * kPointerSize)); | 825 Immediate(kRegisterZero - num_saved_registers_ * kPointerSize)); |
| 805 __ j(greater, &init_loop); | 826 __ j(greater, &init_loop); |
| 806 } else { // Unroll the loop. | 827 } else { // Unroll the loop. |
| 807 for (int i = 0; i < num_saved_registers_; i++) { | 828 for (int i = 0; i < num_saved_registers_; i++) { |
| 808 __ movq(register_location(i), rax); | 829 __ movq(register_location(i), rax); |
| 809 } | 830 } |
| 810 } | 831 } |
| 811 } | 832 } |
| 812 | 833 |
| 813 // Initialize backtrack stack pointer. | 834 // Initialize backtrack stack pointer. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 824 __ movq(rdx, Operand(rbp, kStartIndex)); | 845 __ movq(rdx, Operand(rbp, kStartIndex)); |
| 825 __ movq(rbx, Operand(rbp, kRegisterOutput)); | 846 __ movq(rbx, Operand(rbp, kRegisterOutput)); |
| 826 __ movq(rcx, Operand(rbp, kInputEnd)); | 847 __ movq(rcx, Operand(rbp, kInputEnd)); |
| 827 __ subq(rcx, Operand(rbp, kInputStart)); | 848 __ subq(rcx, Operand(rbp, kInputStart)); |
| 828 if (mode_ == UC16) { | 849 if (mode_ == UC16) { |
| 829 __ lea(rcx, Operand(rcx, rdx, times_2, 0)); | 850 __ lea(rcx, Operand(rcx, rdx, times_2, 0)); |
| 830 } else { | 851 } else { |
| 831 __ addq(rcx, rdx); | 852 __ addq(rcx, rdx); |
| 832 } | 853 } |
| 833 for (int i = 0; i < num_saved_registers_; i++) { | 854 for (int i = 0; i < num_saved_registers_; i++) { |
| 855 #ifndef V8_TARGET_ARCH_X32 |
| 834 __ movq(rax, register_location(i)); | 856 __ movq(rax, register_location(i)); |
| 857 #else |
| 858 __ movsxlq(rax, register_location(i)); |
| 859 #endif |
| 835 if (i == 0 && global_with_zero_length_check()) { | 860 if (i == 0 && global_with_zero_length_check()) { |
| 836 // Keep capture start in rdx for the zero-length check later. | 861 // Keep capture start in rdx for the zero-length check later. |
| 837 __ movq(rdx, rax); | 862 __ movq(rdx, rax); |
| 838 } | 863 } |
| 839 __ addq(rax, rcx); // Convert to index from start, not end. | 864 __ addq(rax, rcx); // Convert to index from start, not end. |
| 840 if (mode_ == UC16) { | 865 if (mode_ == UC16) { |
| 841 __ sar(rax, Immediate(1)); // Convert byte index to character index. | 866 __ sar(rax, Immediate(1)); // Convert byte index to character index. |
| 842 } | 867 } |
| 843 __ movl(Operand(rbx, i * kIntSize), rax); | 868 __ movl(Operand(rbx, i * kIntSize), rax); |
| 844 } | 869 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 868 // Special case for zero-length matches. | 893 // Special case for zero-length matches. |
| 869 // rdx: capture start index | 894 // rdx: capture start index |
| 870 __ cmpq(rdi, rdx); | 895 __ cmpq(rdi, rdx); |
| 871 // Not a zero-length match, restart. | 896 // Not a zero-length match, restart. |
| 872 __ j(not_equal, &load_char_start_regexp); | 897 __ j(not_equal, &load_char_start_regexp); |
| 873 // rdi (offset from the end) is zero if we already reached the end. | 898 // rdi (offset from the end) is zero if we already reached the end. |
| 874 __ testq(rdi, rdi); | 899 __ testq(rdi, rdi); |
| 875 __ j(zero, &exit_label_, Label::kNear); | 900 __ j(zero, &exit_label_, Label::kNear); |
| 876 // Advance current position after a zero-length match. | 901 // Advance current position after a zero-length match. |
| 877 if (mode_ == UC16) { | 902 if (mode_ == UC16) { |
| 878 __ addq(rdi, Immediate(2)); | 903 __k addq(rdi, Immediate(2)); |
| 879 } else { | 904 } else { |
| 880 __ incq(rdi); | 905 __k incq(rdi); |
| 881 } | 906 } |
| 882 } | 907 } |
| 883 | 908 |
| 884 __ jmp(&load_char_start_regexp); | 909 __ jmp(&load_char_start_regexp); |
| 885 } else { | 910 } else { |
| 886 __ movq(rax, Immediate(SUCCESS)); | 911 __ movq(rax, Immediate(SUCCESS)); |
| 887 } | 912 } |
| 888 } | 913 } |
| 889 | 914 |
| 890 __ bind(&exit_label_); | 915 __ bind(&exit_label_); |
| 891 if (global()) { | 916 if (global()) { |
| 892 // Return the number of successful captures. | 917 // Return the number of successful captures. |
| 893 __ movq(rax, Operand(rbp, kSuccessfulCaptures)); | 918 __ movq(rax, Operand(rbp, kSuccessfulCaptures)); |
| 894 } | 919 } |
| 895 | 920 |
| 896 __ bind(&return_rax); | 921 __ bind(&return_rax); |
| 897 #ifdef _WIN64 | 922 #ifdef _WIN64 |
| 898 // Restore callee save registers. | 923 // Restore callee save registers. |
| 899 __ lea(rsp, Operand(rbp, kLastCalleeSaveRegister)); | 924 __ lea(rsp, Operand(rbp, kLastCalleeSaveRegister)); |
| 900 __ pop(rbx); | 925 __k pop(rbx); |
| 901 __ pop(rdi); | 926 __k pop(rdi); |
| 902 __ pop(rsi); | 927 __k pop(rsi); |
| 903 // Stack now at rbp. | 928 // Stack now at rbp. |
| 904 #else | 929 #else |
| 905 // Restore callee save register. | 930 // Restore callee save register. |
| 906 __ movq(rbx, Operand(rbp, kBackup_rbx)); | 931 __ movq(rbx, Operand(rbp, kBackup_rbx)); |
| 907 // Skip rsp to rbp. | 932 // Skip rsp to rbp. |
| 908 __ movq(rsp, rbp); | 933 __ movq(rsp, rbp); |
| 909 #endif | 934 #endif |
| 910 // Exit function frame, restore previous one. | 935 // Exit function frame, restore previous one. |
| 911 __ pop(rbp); | 936 __ pop(rbp); |
| 912 __ ret(0); | 937 __ ret(0); |
| 913 | 938 |
| 914 // Backtrack code (branch target for conditional backtracks). | 939 // Backtrack code (branch target for conditional backtracks). |
| 915 if (backtrack_label_.is_linked()) { | 940 if (backtrack_label_.is_linked()) { |
| 916 __ bind(&backtrack_label_); | 941 __ bind(&backtrack_label_); |
| 917 Backtrack(); | 942 Backtrack(); |
| 918 } | 943 } |
| 919 | 944 |
| 920 Label exit_with_exception; | 945 Label exit_with_exception; |
| 921 | 946 |
| 922 // Preempt-code | 947 // Preempt-code |
| 923 if (check_preempt_label_.is_linked()) { | 948 if (check_preempt_label_.is_linked()) { |
| 924 SafeCallTarget(&check_preempt_label_); | 949 SafeCallTarget(&check_preempt_label_); |
| 925 | 950 |
| 926 __ push(backtrack_stackpointer()); | 951 __k push(backtrack_stackpointer()); |
| 927 __ push(rdi); | 952 __k push(rdi); |
| 928 | 953 |
| 929 CallCheckStackGuardState(); | 954 CallCheckStackGuardState(); |
| 930 __ testq(rax, rax); | 955 __ testq(rax, rax); |
| 931 // If returning non-zero, we should end execution with the given | 956 // If returning non-zero, we should end execution with the given |
| 932 // result as return value. | 957 // result as return value. |
| 933 __ j(not_zero, &return_rax); | 958 __ j(not_zero, &return_rax); |
| 934 | 959 |
| 935 // Restore registers. | 960 // Restore registers. |
| 936 __ Move(code_object_pointer(), masm_.CodeObject()); | 961 __ Move(code_object_pointer(), masm_.CodeObject()); |
| 937 __ pop(rdi); | 962 __k pop(rdi); |
| 938 __ pop(backtrack_stackpointer()); | 963 __k pop(backtrack_stackpointer()); |
| 939 // String might have moved: Reload esi from frame. | 964 // String might have moved: Reload esi from frame. |
| 940 __ movq(rsi, Operand(rbp, kInputEnd)); | 965 __ movq(rsi, Operand(rbp, kInputEnd)); |
| 941 SafeReturn(); | 966 SafeReturn(); |
| 942 } | 967 } |
| 943 | 968 |
| 944 // Backtrack stack overflow code. | 969 // Backtrack stack overflow code. |
| 945 if (stack_overflow_label_.is_linked()) { | 970 if (stack_overflow_label_.is_linked()) { |
| 946 SafeCallTarget(&stack_overflow_label_); | 971 SafeCallTarget(&stack_overflow_label_); |
| 947 // Reached if the backtrack-stack limit has been hit. | 972 // Reached if the backtrack-stack limit has been hit. |
| 948 | 973 |
| 949 Label grow_failed; | 974 Label grow_failed; |
| 950 // Save registers before calling C function | 975 // Save registers before calling C function |
| 951 #ifndef _WIN64 | 976 #ifndef _WIN64 |
| 952 // Callee-save in Microsoft 64-bit ABI, but not in AMD64 ABI. | 977 // Callee-save in Microsoft 64-bit ABI, but not in AMD64 ABI. |
| 953 __ push(rsi); | 978 __k push(rsi); |
| 954 __ push(rdi); | 979 __k push(rdi); |
| 955 #endif | 980 #endif |
| 956 | 981 |
| 957 // Call GrowStack(backtrack_stackpointer()) | 982 // Call GrowStack(backtrack_stackpointer()) |
| 958 static const int num_arguments = 3; | 983 static const int num_arguments = 3; |
| 959 __ PrepareCallCFunction(num_arguments); | 984 __ PrepareCallCFunction(num_arguments); |
| 960 #ifdef _WIN64 | 985 #ifdef _WIN64 |
| 961 // Microsoft passes parameters in rcx, rdx, r8. | 986 // Microsoft passes parameters in rcx, rdx, r8. |
| 962 // First argument, backtrack stackpointer, is already in rcx. | 987 // First argument, backtrack stackpointer, is already in rcx. |
| 963 __ lea(rdx, Operand(rbp, kStackHighEnd)); // Second argument | 988 __ lea(rdx, Operand(rbp, kStackHighEnd)); // Second argument |
| 964 __ LoadAddress(r8, ExternalReference::isolate_address(isolate())); | 989 __ LoadAddress(r8, ExternalReference::isolate_address(isolate())); |
| 965 #else | 990 #else |
| 966 // AMD64 ABI passes parameters in rdi, rsi, rdx. | 991 // AMD64 ABI passes parameters in rdi, rsi, rdx. |
| 967 __ movq(rdi, backtrack_stackpointer()); // First argument. | 992 __ movq(rdi, backtrack_stackpointer()); // First argument. |
| 968 __ lea(rsi, Operand(rbp, kStackHighEnd)); // Second argument. | 993 __ lea(rsi, Operand(rbp, kStackHighEnd)); // Second argument. |
| 969 __ LoadAddress(rdx, ExternalReference::isolate_address(isolate())); | 994 __ LoadAddress(rdx, ExternalReference::isolate_address(isolate())); |
| 970 #endif | 995 #endif |
| 971 ExternalReference grow_stack = | 996 ExternalReference grow_stack = |
| 972 ExternalReference::re_grow_stack(isolate()); | 997 ExternalReference::re_grow_stack(isolate()); |
| 973 __ CallCFunction(grow_stack, num_arguments); | 998 __ CallCFunction(grow_stack, num_arguments); |
| 974 // If return NULL, we have failed to grow the stack, and | 999 // If return NULL, we have failed to grow the stack, and |
| 975 // must exit with a stack-overflow exception. | 1000 // must exit with a stack-overflow exception. |
| 976 __ testq(rax, rax); | 1001 __ testq(rax, rax); |
| 977 __ j(equal, &exit_with_exception); | 1002 __ j(equal, &exit_with_exception); |
| 978 // Otherwise use return value as new stack pointer. | 1003 // Otherwise use return value as new stack pointer. |
| 979 __ movq(backtrack_stackpointer(), rax); | 1004 __ movq(backtrack_stackpointer(), rax); |
| 980 // Restore saved registers and continue. | 1005 // Restore saved registers and continue. |
| 981 __ Move(code_object_pointer(), masm_.CodeObject()); | 1006 __ Move(code_object_pointer(), masm_.CodeObject()); |
| 982 #ifndef _WIN64 | 1007 #ifndef _WIN64 |
| 983 __ pop(rdi); | 1008 __k pop(rdi); |
| 984 __ pop(rsi); | 1009 __k pop(rsi); |
| 985 #endif | 1010 #endif |
| 986 SafeReturn(); | 1011 SafeReturn(); |
| 987 } | 1012 } |
| 988 | 1013 |
| 989 if (exit_with_exception.is_linked()) { | 1014 if (exit_with_exception.is_linked()) { |
| 990 // If any of the code above needed to exit with an exception. | 1015 // If any of the code above needed to exit with an exception. |
| 991 __ bind(&exit_with_exception); | 1016 __ bind(&exit_with_exception); |
| 992 // Exit with Result EXCEPTION(-1) to signal thrown exception. | 1017 // Exit with Result EXCEPTION(-1) to signal thrown exception. |
| 993 __ Set(rax, EXCEPTION); | 1018 __ Set(rax, EXCEPTION); |
| 994 __ jmp(&return_rax); | 1019 __ jmp(&return_rax); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1078 | 1103 |
| 1079 void RegExpMacroAssemblerX64::PushRegister(int register_index, | 1104 void RegExpMacroAssemblerX64::PushRegister(int register_index, |
| 1080 StackCheckFlag check_stack_limit) { | 1105 StackCheckFlag check_stack_limit) { |
| 1081 __ movq(rax, register_location(register_index)); | 1106 __ movq(rax, register_location(register_index)); |
| 1082 Push(rax); | 1107 Push(rax); |
| 1083 if (check_stack_limit) CheckStackLimit(); | 1108 if (check_stack_limit) CheckStackLimit(); |
| 1084 } | 1109 } |
| 1085 | 1110 |
| 1086 | 1111 |
| 1087 void RegExpMacroAssemblerX64::ReadCurrentPositionFromRegister(int reg) { | 1112 void RegExpMacroAssemblerX64::ReadCurrentPositionFromRegister(int reg) { |
| 1113 #ifndef V8_TARGET_ARCH_X32 |
| 1088 __ movq(rdi, register_location(reg)); | 1114 __ movq(rdi, register_location(reg)); |
| 1115 #else |
| 1116 __ movsxlq(rdi, register_location(reg)); |
| 1117 #endif |
| 1089 } | 1118 } |
| 1090 | 1119 |
| 1091 | 1120 |
| 1092 void RegExpMacroAssemblerX64::ReadStackPointerFromRegister(int reg) { | 1121 void RegExpMacroAssemblerX64::ReadStackPointerFromRegister(int reg) { |
| 1122 #ifndef V8_TARGET_ARCH_X32 |
| 1093 __ movq(backtrack_stackpointer(), register_location(reg)); | 1123 __ movq(backtrack_stackpointer(), register_location(reg)); |
| 1094 __ addq(backtrack_stackpointer(), Operand(rbp, kStackHighEnd)); | 1124 __ addq(backtrack_stackpointer(), Operand(rbp, kStackHighEnd)); |
| 1125 #else |
| 1126 __ movsxlq(backtrack_stackpointer(), register_location(reg)); |
| 1127 __ addl(backtrack_stackpointer(), Operand(rbp, kStackHighEnd)); |
| 1128 #endif |
| 1095 } | 1129 } |
| 1096 | 1130 |
| 1097 | 1131 |
| 1098 void RegExpMacroAssemblerX64::SetCurrentPositionFromEnd(int by) { | 1132 void RegExpMacroAssemblerX64::SetCurrentPositionFromEnd(int by) { |
| 1099 Label after_position; | 1133 Label after_position; |
| 1100 __ cmpq(rdi, Immediate(-by * char_size())); | 1134 __ cmpq(rdi, Immediate(-by * char_size())); |
| 1101 __ j(greater_equal, &after_position, Label::kNear); | 1135 __ j(greater_equal, &after_position, Label::kNear); |
| 1102 __ movq(rdi, Immediate(-by * char_size())); | 1136 __k movq(rdi, Immediate(-by * char_size())); |
| 1103 // On RegExp code entry (where this operation is used), the character before | 1137 // On RegExp code entry (where this operation is used), the character before |
| 1104 // the current position is expected to be already loaded. | 1138 // the current position is expected to be already loaded. |
| 1105 // We have advanced the position, so it's safe to read backwards. | 1139 // We have advanced the position, so it's safe to read backwards. |
| 1106 LoadCurrentCharacterUnchecked(-1, 1); | 1140 LoadCurrentCharacterUnchecked(-1, 1); |
| 1107 __ bind(&after_position); | 1141 __ bind(&after_position); |
| 1108 } | 1142 } |
| 1109 | 1143 |
| 1110 | 1144 |
| 1111 void RegExpMacroAssemblerX64::SetRegister(int register_index, int to) { | 1145 void RegExpMacroAssemblerX64::SetRegister(int register_index, int to) { |
| 1112 ASSERT(register_index >= num_saved_registers_); // Reserved for positions! | 1146 ASSERT(register_index >= num_saved_registers_); // Reserved for positions! |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1162 // First argument: Next address on the stack (will be address of | 1196 // First argument: Next address on the stack (will be address of |
| 1163 // return address). | 1197 // return address). |
| 1164 __ lea(rcx, Operand(rsp, -kPointerSize)); | 1198 __ lea(rcx, Operand(rsp, -kPointerSize)); |
| 1165 #else | 1199 #else |
| 1166 // Third argument: RegExp code frame pointer. | 1200 // Third argument: RegExp code frame pointer. |
| 1167 __ movq(rdx, rbp); | 1201 __ movq(rdx, rbp); |
| 1168 // Second argument: Code* of self. | 1202 // Second argument: Code* of self. |
| 1169 __ movq(rsi, code_object_pointer()); | 1203 __ movq(rsi, code_object_pointer()); |
| 1170 // First argument: Next address on the stack (will be address of | 1204 // First argument: Next address on the stack (will be address of |
| 1171 // return address). | 1205 // return address). |
| 1206 #ifndef V8_TARGET_ARCH_X32 |
| 1172 __ lea(rdi, Operand(rsp, -kPointerSize)); | 1207 __ lea(rdi, Operand(rsp, -kPointerSize)); |
| 1208 #else |
| 1209 __ leal(rdi, Operand(rsp, -kHWRegSize)); |
| 1210 #endif |
| 1173 #endif | 1211 #endif |
| 1174 ExternalReference stack_check = | 1212 ExternalReference stack_check = |
| 1175 ExternalReference::re_check_stack_guard_state(isolate()); | 1213 ExternalReference::re_check_stack_guard_state(isolate()); |
| 1176 __ CallCFunction(stack_check, num_arguments); | 1214 __ CallCFunction(stack_check, num_arguments); |
| 1177 } | 1215 } |
| 1178 | 1216 |
| 1179 | 1217 |
| 1180 // Helper function for reading a value out of a stack frame. | 1218 // Helper function for reading a value out of a stack frame. |
| 1181 template <typename T> | 1219 template <typename T> |
| 1182 static T& frame_entry(Address re_frame, int frame_offset) { | 1220 static T& frame_entry(Address re_frame, int frame_offset) { |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1369 | 1407 |
| 1370 void RegExpMacroAssemblerX64::Push(Label* backtrack_target) { | 1408 void RegExpMacroAssemblerX64::Push(Label* backtrack_target) { |
| 1371 __ subq(backtrack_stackpointer(), Immediate(kIntSize)); | 1409 __ subq(backtrack_stackpointer(), Immediate(kIntSize)); |
| 1372 __ movl(Operand(backtrack_stackpointer(), 0), backtrack_target); | 1410 __ movl(Operand(backtrack_stackpointer(), 0), backtrack_target); |
| 1373 MarkPositionForCodeRelativeFixup(); | 1411 MarkPositionForCodeRelativeFixup(); |
| 1374 } | 1412 } |
| 1375 | 1413 |
| 1376 | 1414 |
| 1377 void RegExpMacroAssemblerX64::Pop(Register target) { | 1415 void RegExpMacroAssemblerX64::Pop(Register target) { |
| 1378 ASSERT(!target.is(backtrack_stackpointer())); | 1416 ASSERT(!target.is(backtrack_stackpointer())); |
| 1379 __ movsxlq(target, Operand(backtrack_stackpointer(), 0)); | 1417 __k movsxlq(target, Operand(backtrack_stackpointer(), 0)); |
| 1380 // Notice: This updates flags, unlike normal Pop. | 1418 // Notice: This updates flags, unlike normal Pop. |
| 1381 __ addq(backtrack_stackpointer(), Immediate(kIntSize)); | 1419 __ addq(backtrack_stackpointer(), Immediate(kIntSize)); |
| 1382 } | 1420 } |
| 1383 | 1421 |
| 1384 | 1422 |
| 1385 void RegExpMacroAssemblerX64::Drop() { | 1423 void RegExpMacroAssemblerX64::Drop() { |
| 1386 __ addq(backtrack_stackpointer(), Immediate(kIntSize)); | 1424 __ addq(backtrack_stackpointer(), Immediate(kIntSize)); |
| 1387 } | 1425 } |
| 1388 | 1426 |
| 1389 | 1427 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1433 __ movl(current_character(), | 1471 __ movl(current_character(), |
| 1434 Operand(rsi, rdi, times_1, cp_offset * sizeof(uc16))); | 1472 Operand(rsi, rdi, times_1, cp_offset * sizeof(uc16))); |
| 1435 } else { | 1473 } else { |
| 1436 ASSERT(characters == 1); | 1474 ASSERT(characters == 1); |
| 1437 __ movzxwl(current_character(), | 1475 __ movzxwl(current_character(), |
| 1438 Operand(rsi, rdi, times_1, cp_offset * sizeof(uc16))); | 1476 Operand(rsi, rdi, times_1, cp_offset * sizeof(uc16))); |
| 1439 } | 1477 } |
| 1440 } | 1478 } |
| 1441 } | 1479 } |
| 1442 | 1480 |
| 1481 #undef __k |
| 1443 #undef __ | 1482 #undef __ |
| 1444 | 1483 |
| 1445 #endif // V8_INTERPRETED_REGEXP | 1484 #endif // V8_INTERPRETED_REGEXP |
| 1446 | 1485 |
| 1447 }} // namespace v8::internal | 1486 }} // namespace v8::internal |
| 1448 | 1487 |
| 1449 #endif // V8_TARGET_ARCH_X64 | 1488 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |