Chromium Code Reviews| 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 |