OLD | NEW |
---|---|
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 15 matching lines...) Expand all Loading... | |
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 "v8.h" | 28 #include "v8.h" |
29 | 29 |
30 #include "bootstrapper.h" | 30 #include "bootstrapper.h" |
31 #include "codegen-inl.h" | 31 #include "codegen-inl.h" |
32 #include "compiler.h" | 32 #include "compiler.h" |
33 #include "debug.h" | 33 #include "debug.h" |
34 #include "ic-inl.h" | 34 #include "ic-inl.h" |
35 #include "parser.h" | 35 #include "parser.h" |
36 #include "regexp-macro-assembler.h" | |
36 #include "register-allocator-inl.h" | 37 #include "register-allocator-inl.h" |
37 #include "scopes.h" | 38 #include "scopes.h" |
38 | 39 |
39 namespace v8 { | 40 namespace v8 { |
40 namespace internal { | 41 namespace internal { |
41 | 42 |
42 #define __ ACCESS_MASM(masm_) | 43 #define __ ACCESS_MASM(masm_) |
43 | 44 |
44 // ------------------------------------------------------------------------- | 45 // ------------------------------------------------------------------------- |
45 // Platform-specific DeferredCode functions. | 46 // Platform-specific DeferredCode functions. |
(...skipping 3902 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3948 | 3949 |
3949 | 3950 |
3950 void CodeGenerator::GenerateRegExpExec(ZoneList<Expression*>* args) { | 3951 void CodeGenerator::GenerateRegExpExec(ZoneList<Expression*>* args) { |
3951 ASSERT_EQ(args->length(), 4); | 3952 ASSERT_EQ(args->length(), 4); |
3952 | 3953 |
3953 // Load the arguments on the stack and call the runtime system. | 3954 // Load the arguments on the stack and call the runtime system. |
3954 Load(args->at(0)); | 3955 Load(args->at(0)); |
3955 Load(args->at(1)); | 3956 Load(args->at(1)); |
3956 Load(args->at(2)); | 3957 Load(args->at(2)); |
3957 Load(args->at(3)); | 3958 Load(args->at(3)); |
3958 Result result = frame_->CallRuntime(Runtime::kRegExpExec, 4); | 3959 RegExpExecStub stub; |
3960 Result result = frame_->CallStub(&stub, 4); | |
3959 frame_->Push(&result); | 3961 frame_->Push(&result); |
3960 } | 3962 } |
3961 | 3963 |
3962 | 3964 |
3963 void CodeGenerator::GenerateStringAdd(ZoneList<Expression*>* args) { | 3965 void CodeGenerator::GenerateStringAdd(ZoneList<Expression*>* args) { |
3964 ASSERT_EQ(2, args->length()); | 3966 ASSERT_EQ(2, args->length()); |
3965 | 3967 |
3966 Load(args->at(0)); | 3968 Load(args->at(0)); |
3967 Load(args->at(1)); | 3969 Load(args->at(1)); |
3968 | 3970 |
(...skipping 2587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6556 break; | 6558 break; |
6557 case Token::BIT_NOT: | 6559 case Token::BIT_NOT: |
6558 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION); | 6560 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION); |
6559 break; | 6561 break; |
6560 default: | 6562 default: |
6561 UNREACHABLE(); | 6563 UNREACHABLE(); |
6562 } | 6564 } |
6563 } | 6565 } |
6564 | 6566 |
6565 | 6567 |
6568 void RegExpExecStub::Generate(MacroAssembler* masm) { | |
6569 // Just jump directly to runtime if native RegExp is not selected at compile | |
6570 // time or if regexp entry in generated code is turned off runtime switch or | |
6571 // at compilation. | |
6572 #ifndef V8_NATIVE_REGEXP | |
6573 __ TailCallRuntime(ExternalReference(Runtime::kRegExpExec), 4, 1); | |
6574 #endif | |
6575 if (!FLAG_regexp_entry_native) { | |
6576 __ TailCallRuntime(ExternalReference(Runtime::kRegExpExec), 4, 1); | |
6577 return; | |
6578 } | |
6579 | |
6580 // Stack frame on entry. | |
6581 // esp[0]: return address | |
6582 // esp[8]: last_match_info (expected JSArray) | |
6583 // esp[16]: previous index | |
6584 // esp[24]: subject string | |
6585 // esp[32]: JSRegExp object | |
6586 | |
6587 static const int kLastMatchInfoOffset = 1 * kPointerSize; | |
6588 static const int kPreviousIndexOffset = 2 * kPointerSize; | |
6589 static const int kSubjectOffset = 3 * kPointerSize; | |
6590 static const int kJSRegExpOffset = 4 * kPointerSize; | |
6591 | |
6592 Label runtime; | |
6593 | |
6594 // Ensure that a RegExp stack is allocated. | |
6595 ExternalReference address_of_regexp_stack_memory_address = | |
6596 ExternalReference::address_of_regexp_stack_memory_address(); | |
6597 ExternalReference address_of_regexp_stack_memory_size = | |
6598 ExternalReference::address_of_regexp_stack_memory_size(); | |
6599 __ movq(kScratchRegister, address_of_regexp_stack_memory_size); | |
6600 __ movq(kScratchRegister, Operand(kScratchRegister, 0)); | |
6601 __ testq(kScratchRegister, kScratchRegister); | |
6602 __ j(zero, &runtime); | |
6603 | |
6604 | |
6605 // Check that the first argument is a JSRegExp object. | |
6606 __ movq(rax, Operand(rsp, kJSRegExpOffset)); | |
6607 __ JumpIfSmi(rax, &runtime); | |
6608 __ CmpObjectType(rax, JS_REGEXP_TYPE, kScratchRegister); | |
6609 __ j(not_equal, &runtime); | |
6610 // Check that the RegExp has been compiled (data contains a fixed array). | |
6611 __ movq(rcx, FieldOperand(rax, JSRegExp::kDataOffset)); | |
6612 if (FLAG_debug_code) { | |
6613 Condition is_smi = masm->CheckSmi(rcx); | |
6614 __ Check(NegateCondition(is_smi), | |
6615 "Unexpected type for RegExp data, FixedArray expected"); | |
6616 __ CmpObjectType(rcx, FIXED_ARRAY_TYPE, kScratchRegister); | |
6617 __ Check(equal, "Unexpected type for RegExp data, FixedArray expected"); | |
6618 } | |
6619 | |
6620 // rcx: RegExp data (FixedArray) | |
6621 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. | |
6622 __ movq(rbx, FieldOperand(rcx, JSRegExp::kDataTagOffset)); | |
6623 __ SmiCompare(rbx, Smi::FromInt(JSRegExp::IRREGEXP)); | |
6624 __ j(not_equal, &runtime); | |
6625 | |
6626 // rcx: RegExp data (FixedArray) | |
6627 // Check that the number of captures fit in the static offsets vector buffer. | |
6628 __ movq(rdx, FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset)); | |
6629 // Calculate number of capture registers (number_of_captures + 1) * 2. | |
6630 __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rdx, 1); | |
6631 __ addq(rdx, Immediate(2)); // rdx was number_of_captures * 2. | |
6632 // Check that the static offsets vector buffer is large enough. | |
6633 __ cmpq(rdx, Immediate(OffsetsVector::kStaticOffsetsVectorSize)); | |
6634 __ j(above, &runtime); | |
6635 | |
6636 // rcx: RegExp data (FixedArray) | |
6637 // rdx: Number of capture registers | |
6638 // Check that the second argument is a string. | |
6639 __ movq(rax, Operand(rsp, kSubjectOffset)); | |
6640 __ JumpIfSmi(rax, &runtime); | |
6641 Condition is_string = masm->IsObjectStringType(rax, rbx, rbx); | |
6642 __ j(NegateCondition(is_string), &runtime); | |
6643 // Get the length of the string to rbx. | |
6644 __ movl(rbx, FieldOperand(rax, String::kLengthOffset)); | |
6645 | |
6646 // rbx: Length of subject string | |
6647 // rcx: RegExp data (FixedArray) | |
6648 // rdx: Number of capture registers | |
6649 // Check that the third argument is a positive smi less than the string | |
6650 // length. A negative value will be greater (usigned comparison). | |
6651 __ movq(rax, Operand(rsp, kPreviousIndexOffset)); | |
6652 __ SmiToInteger32(rax, rax); | |
6653 __ cmpl(rax, rbx); | |
6654 __ j(greater, &runtime); | |
Lasse Reichstein
2010/01/29 08:09:08
greater -> above
Søren Thygesen Gjesse
2010/01/29 13:06:53
Thanks, fixed in ia32 version as well.
| |
6655 | |
6656 // rcx: RegExp data (FixedArray) | |
6657 // rdx: Number of capture registers | |
6658 // Check that the fourth object is a JSArray object. | |
6659 __ movq(rax, Operand(rsp, kLastMatchInfoOffset)); | |
6660 __ JumpIfSmi(rax, &runtime); | |
6661 __ CmpObjectType(rax, JS_ARRAY_TYPE, kScratchRegister); | |
6662 __ j(not_equal, &runtime); | |
6663 // Check that the JSArray is in fast case. | |
6664 __ movq(rbx, FieldOperand(rax, JSArray::kElementsOffset)); | |
6665 __ movq(rax, FieldOperand(rbx, HeapObject::kMapOffset)); | |
6666 __ Cmp(rax, Factory::fixed_array_map()); | |
6667 __ j(not_equal, &runtime); | |
6668 // Check that the last match info has space for the capture registers and the | |
6669 // additional information. Ensure no overflow in add. | |
6670 ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset); | |
6671 __ movl(rax, FieldOperand(rbx, FixedArray::kLengthOffset)); | |
6672 __ addl(rdx, Immediate(RegExpImpl::kLastMatchOverhead)); | |
6673 __ cmpl(rdx, rax); | |
6674 __ j(greater, &runtime); | |
6675 | |
6676 // ecx: RegExp data (FixedArray) | |
6677 // Check the representation and encoding of the subject string. | |
6678 Label seq_string, seq_two_byte_string, check_code; | |
6679 const int kStringRepresentationEncodingMask = | |
6680 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; | |
6681 __ movq(rax, Operand(rsp, kSubjectOffset)); | |
6682 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | |
6683 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | |
6684 __ andb(rbx, Immediate(kStringRepresentationEncodingMask)); | |
6685 // First check for sequential string. | |
6686 ASSERT_EQ(0, kStringTag); | |
6687 ASSERT_EQ(0, kSeqStringTag); | |
6688 __ testb(rbx, Immediate(kIsNotStringMask | kStringRepresentationMask)); | |
6689 __ j(zero, &seq_string); | |
6690 | |
6691 // Check for flat cons string. | |
6692 // A flat cons string is a cons string where the second part is the empty | |
6693 // string. In that case the subject string is just the first part of the cons | |
6694 // string. Also in this case the first part of the cons string is known to be | |
6695 // a sequential string or an external string. | |
6696 __ movl(rdx, rbx); | |
6697 __ andb(rdx, Immediate(kStringRepresentationMask)); | |
6698 __ cmpb(rdx, Immediate(kConsStringTag)); | |
6699 __ j(not_equal, &runtime); | |
6700 __ movq(rdx, FieldOperand(rax, ConsString::kSecondOffset)); | |
6701 __ Cmp(rdx, Factory::empty_string()); | |
6702 __ j(not_equal, &runtime); | |
6703 __ movq(rax, FieldOperand(rax, ConsString::kFirstOffset)); | |
6704 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | |
6705 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | |
6706 ASSERT_EQ(0, kSequentialStringTag); | |
6707 __ testb(rbx, Immediate(kStringRepresentationMask)); | |
6708 __ j(not_zero, &runtime); | |
6709 __ andb(rbx, Immediate(kStringRepresentationEncodingMask)); | |
Lasse Reichstein
2010/01/29 08:09:08
Do you need the representation bits any more? You
Søren Thygesen Gjesse
2010/01/29 13:06:53
The reason is that the jump to label seq_string fr
| |
6710 | |
6711 __ bind(&seq_string); | |
6712 // rax: subject string (sequential either ascii to two byte) | |
6713 // rbx: suject string type & kStringRepresentationEncodingMask | |
6714 // rcx: RegExp data (FixedArray) | |
6715 // Check that the irregexp code has been generated for an ascii string. If | |
6716 // it has, the field contains a code object otherwise it contains the hole. | |
6717 __ cmpb(rbx, Immediate(kStringTag | kSeqStringTag | kTwoByteStringTag)); | |
6718 __ j(equal, &seq_two_byte_string); | |
6719 if (FLAG_debug_code) { | |
6720 __ cmpb(rbx, Immediate(kStringTag | kSeqStringTag | kAsciiStringTag)); | |
6721 __ Check(equal, "Expected sequential ascii string"); | |
6722 } | |
6723 __ movq(r12, FieldOperand(rcx, JSRegExp::kDataAsciiCodeOffset)); | |
6724 __ Set(rdi, 1); // Type is ascii. | |
6725 __ jmp(&check_code); | |
6726 | |
6727 __ bind(&seq_two_byte_string); | |
6728 // rax: subject string | |
6729 // rcx: RegExp data (FixedArray) | |
6730 __ movq(r12, FieldOperand(rcx, JSRegExp::kDataUC16CodeOffset)); | |
6731 __ Set(rdi, 0); // Type is two byte. | |
6732 | |
6733 __ bind(&check_code); | |
6734 // Check that the irregexp code has been generated for the actual string | |
6735 // encoding. If it has, the field contains a code object otherwise it contains | |
6736 // the hole. | |
6737 __ CmpObjectType(r12, CODE_TYPE, kScratchRegister); | |
6738 __ j(not_equal, &runtime); | |
6739 | |
6740 // rax: subject string | |
6741 // rdi: encoding of subject string (1 if ascii, 0 if two_byte); | |
6742 // r12: code | |
6743 // Load used arguments before starting to push arguments for call to native | |
6744 // RegExp code to avoid handling changing stack height. | |
6745 __ movq(rbx, Operand(rsp, kPreviousIndexOffset)); | |
6746 __ SmiToInteger64(rbx, rbx); // Previous index from smi. | |
6747 | |
6748 // rax: subject string | |
6749 // rbx: previous index | |
6750 // rdi: encoding of subject string (1 if ascii 0 if two_byte); | |
6751 // r12: code | |
6752 // All checks done. Now push arguments for native regexp code. | |
6753 __ IncrementCounter(&Counters::regexp_entry_native, 1); | |
6754 | |
6755 // rsi is caller save on Windows and used to pass parameter on Linux. | |
6756 __ push(rsi); | |
6757 | |
6758 static const int kRegExpExecuteArguments = 7; | |
6759 __ PrepareCallCFunction(kRegExpExecuteArguments); | |
6760 int argument_slots_on_stack = | |
6761 masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments); | |
6762 | |
6763 // Argument 7: Indicate that this is a direct call from JavaScript. | |
6764 __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kPointerSize), | |
6765 Immediate(1)); | |
6766 | |
6767 // Argument 6: Start (high end) of backtracking stack memory area. | |
6768 __ movq(kScratchRegister, address_of_regexp_stack_memory_address); | |
6769 __ movq(r9, Operand(kScratchRegister, 0)); | |
6770 __ movq(kScratchRegister, address_of_regexp_stack_memory_size); | |
6771 __ addq(r9, Operand(kScratchRegister, 0)); | |
6772 // Argument 6 passed in r9 on Linux and on the stack on Windows. | |
6773 #ifdef _WIN64 | |
6774 __ movq(Operand(rsp, (argument_slots_on_stack - 2) * kPointerSize), r9); | |
6775 #endif | |
6776 | |
6777 // Argument 5: static offsets vector buffer. | |
6778 __ movq(r8, ExternalReference::address_of_static_offsets_vector()); | |
6779 // Argument 5 passed in r8 on Linux and on the stack on Windows. | |
6780 #ifdef _WIN64 | |
6781 __ movq(Operand(rsp, (argument_slots_on_stack - 3) * kPointerSize), r8); | |
6782 #endif | |
6783 | |
6784 // First four arguments are passed in registers on both Linux and Windows. | |
6785 #ifdef _WIN64 | |
6786 Register arg4 = r9; | |
6787 Register arg3 = r8; | |
6788 Register arg2 = rdx; | |
6789 Register arg1 = rcx; | |
6790 #else | |
6791 Register arg4 = rcx; | |
6792 Register arg3 = rdx; | |
6793 Register arg2 = rsi; | |
6794 Register arg1 = rdi; | |
6795 #endif | |
6796 | |
6797 // Keep track on aliasing between argX defined above and the registers used. | |
6798 // rax: subject string | |
6799 // rbx: previous index | |
6800 // rdi: encoding of subject string (1 if ascii 0 if two_byte); | |
6801 // r12: code | |
6802 | |
6803 // Argument 4: End of string data | |
6804 // Argument 3: Start of string data | |
6805 Label setup_two_byte, setup_rest; | |
6806 __ testb(rdi, rdi); | |
6807 __ movl(rdi, FieldOperand(rax, String::kLengthOffset)); | |
6808 __ j(zero, &setup_two_byte); | |
6809 __ lea(arg4, FieldOperand(rax, rdi, times_1, SeqAsciiString::kHeaderSize)); | |
6810 __ lea(arg3, FieldOperand(rax, rbx, times_1, SeqAsciiString::kHeaderSize)); | |
6811 __ jmp(&setup_rest); | |
6812 __ bind(&setup_two_byte); | |
6813 __ lea(arg4, FieldOperand(rax, rdi, times_2, SeqTwoByteString::kHeaderSize)); | |
6814 __ lea(arg3, FieldOperand(rax, rbx, times_2, SeqTwoByteString::kHeaderSize)); | |
6815 | |
6816 __ bind(&setup_rest); | |
6817 // Argument 2: Previous index. | |
6818 __ movq(arg2, rbx); | |
6819 | |
6820 // Argument 1: Subject string. | |
6821 __ movq(arg1, rax); | |
6822 | |
6823 // Locate the code entry and call it. | |
6824 __ addq(r12, Immediate(Code::kHeaderSize - kHeapObjectTag)); | |
6825 __ CallCFunction(r12, kRegExpExecuteArguments); | |
6826 | |
6827 // rsi is caller save, as it is used to pass parameter. | |
6828 __ pop(rsi); | |
6829 | |
6830 // Check the result. | |
6831 Label success; | |
6832 __ cmpq(rax, Immediate(NativeRegExpMacroAssembler::SUCCESS)); | |
6833 __ j(equal, &success); | |
6834 Label failure; | |
6835 __ cmpq(rax, Immediate(NativeRegExpMacroAssembler::FAILURE)); | |
6836 __ j(equal, &failure); | |
6837 __ cmpq(rax, Immediate(NativeRegExpMacroAssembler::EXCEPTION)); | |
6838 // If not exception it can only be retry. Handle that in the runtime system. | |
6839 __ j(not_equal, &runtime); | |
6840 // Result must now be exception. If there is no pending exception already a | |
6841 // stack overflow (on the backtrack stack) was detected in RegExp code but | |
6842 // haven't created the exception yet. Handle that in the runtime system. | |
6843 // TODO(592) Rerunning the RegExp to get the stack overflow exception. | |
6844 ExternalReference pending_exception_address(Top::k_pending_exception_address); | |
6845 __ movq(kScratchRegister, pending_exception_address); | |
6846 __ Cmp(kScratchRegister, Factory::the_hole_value()); | |
6847 __ j(equal, &runtime); | |
6848 __ bind(&failure); | |
6849 // For failure and exception return null. | |
6850 __ Move(rax, Factory::null_value()); | |
6851 __ ret(4 * kPointerSize); | |
6852 | |
6853 // Load RegExp data. | |
6854 __ bind(&success); | |
6855 __ movq(rax, Operand(rsp, kJSRegExpOffset)); | |
6856 __ movq(rcx, FieldOperand(rax, JSRegExp::kDataOffset)); | |
6857 __ movq(rdx, FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset)); | |
6858 // Calculate number of capture registers (number_of_captures + 1) * 2. | |
6859 __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rdx, 1); | |
6860 __ addq(rdx, Immediate(2)); // rdx was number_of_captures * 2. | |
6861 | |
6862 // rdx: Number of capture registers | |
6863 // Load last_match_info which is still known to be a fast case JSArray. | |
6864 __ movq(rax, Operand(rsp, kLastMatchInfoOffset)); | |
6865 __ movq(rbx, FieldOperand(rax, JSArray::kElementsOffset)); | |
6866 | |
6867 // rbx: last_match_info backing store (FixedArray) | |
6868 // rdx: number of capture registers | |
6869 // Store the capture count. | |
6870 __ Integer32ToSmi(kScratchRegister, rdx); | |
6871 __ movq(FieldOperand(rbx, RegExpImpl::kLastCaptureCountOffset), | |
6872 kScratchRegister); | |
6873 // Store last subject and last input. | |
6874 __ movq(rax, Operand(rsp, kSubjectOffset)); | |
6875 __ movq(FieldOperand(rbx, RegExpImpl::kLastSubjectOffset), rax); | |
6876 __ movq(rcx, rbx); | |
6877 __ RecordWrite(rcx, RegExpImpl::kLastSubjectOffset, rax, rdi); | |
6878 __ movq(rax, Operand(rsp, kSubjectOffset)); | |
6879 __ movq(FieldOperand(rbx, RegExpImpl::kLastInputOffset), rax); | |
6880 __ movq(rcx, rbx); | |
6881 __ RecordWrite(rcx, RegExpImpl::kLastInputOffset, rax, rdi); | |
6882 | |
6883 // Get the static offsets vector filled by the native regexp code. | |
6884 __ movq(rcx, ExternalReference::address_of_static_offsets_vector()); | |
6885 | |
6886 // rbx: last_match_info backing store (FixedArray) | |
6887 // rcx: offsets vector | |
6888 // rdx: number of capture registers | |
6889 Label next_capture, done; | |
6890 __ movq(rax, Operand(rsp, kPreviousIndexOffset)); | |
6891 // Capture register counter starts from number of capture registers and | |
6892 // counts down until wraping after zero. | |
6893 __ bind(&next_capture); | |
6894 __ subq(rdx, Immediate(1)); | |
6895 __ j(negative, &done); | |
6896 // Read the value from the static offsets vector buffer and make it a smi. | |
6897 __ movl(rdi, Operand(rcx, rdx, times_int_size, 0)); | |
6898 __ Integer32ToSmi(rdi, rdi, &runtime); | |
6899 // Add previous index (from its stack slot) if value is not negative. | |
6900 Label capture_negative; | |
6901 // Negative flag set by smi convertion above. | |
6902 __ j(negative, &capture_negative); | |
6903 __ SmiAdd(rdi, rdi, rax, &runtime); // Add previous index. | |
6904 __ bind(&capture_negative); | |
6905 // Store the smi value in the last match info. | |
6906 __ movq(FieldOperand(rbx, | |
6907 rdx, | |
6908 times_pointer_size, | |
6909 RegExpImpl::kFirstCaptureOffset), | |
6910 rdi); | |
6911 __ jmp(&next_capture); | |
6912 __ bind(&done); | |
6913 | |
6914 // Return last match info. | |
6915 __ movq(rax, Operand(rsp, kLastMatchInfoOffset)); | |
6916 __ ret(4 * kPointerSize); | |
6917 | |
6918 // Do the runtime call to execute the regexp. | |
6919 __ bind(&runtime); | |
6920 __ TailCallRuntime(ExternalReference(Runtime::kRegExpExec), 4, 1); | |
6921 } | |
6922 | |
6923 | |
6566 void CompareStub::Generate(MacroAssembler* masm) { | 6924 void CompareStub::Generate(MacroAssembler* masm) { |
6567 Label call_builtin, done; | 6925 Label call_builtin, done; |
6568 | 6926 |
6569 // NOTICE! This code is only reached after a smi-fast-case check, so | 6927 // NOTICE! This code is only reached after a smi-fast-case check, so |
6570 // it is certain that at least one operand isn't a smi. | 6928 // it is certain that at least one operand isn't a smi. |
6571 | 6929 |
6572 if (cc_ == equal) { // Both strict and non-strict. | 6930 if (cc_ == equal) { // Both strict and non-strict. |
6573 Label slow; // Fallthrough label. | 6931 Label slow; // Fallthrough label. |
6574 // Equality is almost reflexive (everything but NaN), so start by testing | 6932 // Equality is almost reflexive (everything but NaN), so start by testing |
6575 // for "identity and not NaN". | 6933 // for "identity and not NaN". |
(...skipping 2180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8756 // Call the function from C++. | 9114 // Call the function from C++. |
8757 return FUNCTION_CAST<ModuloFunction>(buffer); | 9115 return FUNCTION_CAST<ModuloFunction>(buffer); |
8758 } | 9116 } |
8759 | 9117 |
8760 #endif | 9118 #endif |
8761 | 9119 |
8762 | 9120 |
8763 #undef __ | 9121 #undef __ |
8764 | 9122 |
8765 } } // namespace v8::internal | 9123 } } // namespace v8::internal |
OLD | NEW |