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 14 matching lines...) Expand all Loading... |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #include "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 "jsregexp.h" |
35 #include "parser.h" | 36 #include "parser.h" |
| 37 #include "regexp-macro-assembler.h" |
| 38 #include "regexp-stack.h" |
36 #include "register-allocator-inl.h" | 39 #include "register-allocator-inl.h" |
37 #include "runtime.h" | 40 #include "runtime.h" |
38 #include "scopes.h" | 41 #include "scopes.h" |
39 #include "virtual-frame-inl.h" | 42 #include "virtual-frame-inl.h" |
40 | 43 |
41 namespace v8 { | 44 namespace v8 { |
42 namespace internal { | 45 namespace internal { |
43 | 46 |
44 #define __ ACCESS_MASM(masm_) | 47 #define __ ACCESS_MASM(masm_) |
45 | 48 |
(...skipping 3962 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4008 } | 4011 } |
4009 | 4012 |
4010 | 4013 |
4011 void CodeGenerator::GenerateRegExpExec(ZoneList<Expression*>* args) { | 4014 void CodeGenerator::GenerateRegExpExec(ZoneList<Expression*>* args) { |
4012 ASSERT_EQ(4, args->length()); | 4015 ASSERT_EQ(4, args->length()); |
4013 | 4016 |
4014 Load(args->at(0)); | 4017 Load(args->at(0)); |
4015 Load(args->at(1)); | 4018 Load(args->at(1)); |
4016 Load(args->at(2)); | 4019 Load(args->at(2)); |
4017 Load(args->at(3)); | 4020 Load(args->at(3)); |
4018 | 4021 RegExpExecStub stub; |
4019 frame_->CallRuntime(Runtime::kRegExpExec, 4); | 4022 frame_->CallStub(&stub, 4); |
4020 frame_->EmitPush(r0); | 4023 frame_->EmitPush(r0); |
4021 } | 4024 } |
4022 | 4025 |
4023 | 4026 |
4024 void CodeGenerator::GenerateRegExpConstructResult(ZoneList<Expression*>* args) { | 4027 void CodeGenerator::GenerateRegExpConstructResult(ZoneList<Expression*>* args) { |
4025 // No stub. This code only occurs a few times in regexp.js. | 4028 // No stub. This code only occurs a few times in regexp.js. |
4026 const int kMaxInlineLength = 100; | 4029 const int kMaxInlineLength = 100; |
4027 ASSERT_EQ(3, args->length()); | 4030 ASSERT_EQ(3, args->length()); |
4028 Load(args->at(0)); // Size of array, smi. | 4031 Load(args->at(0)); // Size of array, smi. |
4029 Load(args->at(1)); // "index" property value. | 4032 Load(args->at(1)); // "index" property value. |
(...skipping 3465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7495 __ bind(&done); | 7498 __ bind(&done); |
7496 __ add(sp, sp, Operand(3 * kPointerSize)); | 7499 __ add(sp, sp, Operand(3 * kPointerSize)); |
7497 __ Ret(); | 7500 __ Ret(); |
7498 | 7501 |
7499 // Do the runtime call to allocate the arguments object. | 7502 // Do the runtime call to allocate the arguments object. |
7500 __ bind(&runtime); | 7503 __ bind(&runtime); |
7501 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); | 7504 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); |
7502 } | 7505 } |
7503 | 7506 |
7504 | 7507 |
| 7508 void RegExpExecStub::Generate(MacroAssembler* masm) { |
| 7509 // Just jump directly to runtime if native RegExp is not selected at compile |
| 7510 // time or if regexp entry in generated code is turned off runtime switch or |
| 7511 // at compilation. |
| 7512 #ifndef V8_NATIVE_REGEXP |
| 7513 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
| 7514 #else // V8_NATIVE_REGEXP |
| 7515 if (!FLAG_regexp_entry_native) { |
| 7516 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
| 7517 return; |
| 7518 } |
| 7519 |
| 7520 // Stack frame on entry. |
| 7521 // sp[0]: last_match_info (expected JSArray) |
| 7522 // sp[4]: previous index |
| 7523 // sp[8]: subject string |
| 7524 // sp[12]: JSRegExp object |
| 7525 |
| 7526 static const int kLastMatchInfoOffset = 0 * kPointerSize; |
| 7527 static const int kPreviousIndexOffset = 1 * kPointerSize; |
| 7528 static const int kSubjectOffset = 2 * kPointerSize; |
| 7529 static const int kJSRegExpOffset = 3 * kPointerSize; |
| 7530 |
| 7531 Label runtime, invoke_regexp; |
| 7532 |
| 7533 // Allocation of registers for this function. These are in callee save |
| 7534 // registers and will be preserved by the call to the native RegExp code, as |
| 7535 // this code is called using the normal C calling convention. When calling |
| 7536 // directly from generated code the native RegExp code will not do a GC and |
| 7537 // therefore the content of these registers are safe to use after the call. |
| 7538 Register subject = r4; |
| 7539 Register regexp_data = r5; |
| 7540 Register last_match_info_elements = r6; |
| 7541 |
| 7542 // Ensure that a RegExp stack is allocated. |
| 7543 ExternalReference address_of_regexp_stack_memory_address = |
| 7544 ExternalReference::address_of_regexp_stack_memory_address(); |
| 7545 ExternalReference address_of_regexp_stack_memory_size = |
| 7546 ExternalReference::address_of_regexp_stack_memory_size(); |
| 7547 __ mov(r0, Operand(address_of_regexp_stack_memory_size)); |
| 7548 __ ldr(r0, MemOperand(r0, 0)); |
| 7549 __ tst(r0, Operand(r0)); |
| 7550 __ b(eq, &runtime); |
| 7551 |
| 7552 // Check that the first argument is a JSRegExp object. |
| 7553 __ ldr(r0, MemOperand(sp, kJSRegExpOffset)); |
| 7554 ASSERT_EQ(0, kSmiTag); |
| 7555 __ tst(r0, Operand(kSmiTagMask)); |
| 7556 __ b(eq, &runtime); |
| 7557 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); |
| 7558 __ b(ne, &runtime); |
| 7559 |
| 7560 // Check that the RegExp has been compiled (data contains a fixed array). |
| 7561 __ ldr(regexp_data, FieldMemOperand(r0, JSRegExp::kDataOffset)); |
| 7562 if (FLAG_debug_code) { |
| 7563 __ tst(regexp_data, Operand(kSmiTagMask)); |
| 7564 __ Check(nz, "Unexpected type for RegExp data, FixedArray expected"); |
| 7565 __ CompareObjectType(regexp_data, r0, r0, FIXED_ARRAY_TYPE); |
| 7566 __ Check(eq, "Unexpected type for RegExp data, FixedArray expected"); |
| 7567 } |
| 7568 |
| 7569 // regexp_data: RegExp data (FixedArray) |
| 7570 // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP. |
| 7571 __ ldr(r0, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset)); |
| 7572 __ cmp(r0, Operand(Smi::FromInt(JSRegExp::IRREGEXP))); |
| 7573 __ b(ne, &runtime); |
| 7574 |
| 7575 // regexp_data: RegExp data (FixedArray) |
| 7576 // Check that the number of captures fit in the static offsets vector buffer. |
| 7577 __ ldr(r2, |
| 7578 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); |
| 7579 // Calculate number of capture registers (number_of_captures + 1) * 2. This |
| 7580 // uses the asumption that smis are 2 * their untagged value. |
| 7581 ASSERT_EQ(0, kSmiTag); |
| 7582 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); |
| 7583 __ add(r2, r2, Operand(2)); // r2 was a smi. |
| 7584 // Check that the static offsets vector buffer is large enough. |
| 7585 __ cmp(r2, Operand(OffsetsVector::kStaticOffsetsVectorSize)); |
| 7586 __ b(hi, &runtime); |
| 7587 |
| 7588 // r2: Number of capture registers |
| 7589 // regexp_data: RegExp data (FixedArray) |
| 7590 // Check that the second argument is a string. |
| 7591 __ ldr(subject, MemOperand(sp, kSubjectOffset)); |
| 7592 __ tst(subject, Operand(kSmiTagMask)); |
| 7593 __ b(eq, &runtime); |
| 7594 Condition is_string = masm->IsObjectStringType(subject, r0); |
| 7595 __ b(NegateCondition(is_string), &runtime); |
| 7596 // Get the length of the string to r3. |
| 7597 __ ldr(r3, FieldMemOperand(subject, String::kLengthOffset)); |
| 7598 |
| 7599 // r2: Number of capture registers |
| 7600 // r3: Length of subject string |
| 7601 // subject: Subject string |
| 7602 // regexp_data: RegExp data (FixedArray) |
| 7603 // Check that the third argument is a positive smi less than the subject |
| 7604 // string length. A negative value will be greater (unsigned comparison). |
| 7605 __ ldr(r0, MemOperand(sp, kPreviousIndexOffset)); |
| 7606 __ cmp(r3, Operand(r0, ASR, kSmiTagSize + kSmiShiftSize)); |
| 7607 __ b(ls, &runtime); |
| 7608 |
| 7609 // r2: Number of capture registers |
| 7610 // subject: Subject string |
| 7611 // regexp_data: RegExp data (FixedArray) |
| 7612 // Check that the fourth object is a JSArray object. |
| 7613 __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset)); |
| 7614 __ tst(r0, Operand(kSmiTagMask)); |
| 7615 __ b(eq, &runtime); |
| 7616 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); |
| 7617 __ b(ne, &runtime); |
| 7618 // Check that the JSArray is in fast case. |
| 7619 __ ldr(last_match_info_elements, |
| 7620 FieldMemOperand(r0, JSArray::kElementsOffset)); |
| 7621 __ ldr(r0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset)); |
| 7622 __ cmp(r0, Operand(Factory::fixed_array_map())); |
| 7623 __ b(ne, &runtime); |
| 7624 // Check that the last match info has space for the capture registers and the |
| 7625 // additional information. |
| 7626 __ ldr(r0, |
| 7627 FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset)); |
| 7628 __ add(r2, r2, Operand(RegExpImpl::kLastMatchOverhead)); |
| 7629 __ cmp(r2, r0); |
| 7630 __ b(gt, &runtime); |
| 7631 |
| 7632 // subject: Subject string |
| 7633 // regexp_data: RegExp data (FixedArray) |
| 7634 // Check the representation and encoding of the subject string. |
| 7635 Label seq_string; |
| 7636 const int kStringRepresentationEncodingMask = |
| 7637 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; |
| 7638 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); |
| 7639 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); |
| 7640 __ and_(r1, r0, Operand(kStringRepresentationEncodingMask)); |
| 7641 // First check for sequential string. |
| 7642 ASSERT_EQ(0, kStringTag); |
| 7643 ASSERT_EQ(0, kSeqStringTag); |
| 7644 __ tst(r1, Operand(kIsNotStringMask | kStringRepresentationMask)); |
| 7645 __ b(eq, &seq_string); |
| 7646 |
| 7647 // subject: Subject string |
| 7648 // regexp_data: RegExp data (FixedArray) |
| 7649 // Check for flat cons string. |
| 7650 // A flat cons string is a cons string where the second part is the empty |
| 7651 // string. In that case the subject string is just the first part of the cons |
| 7652 // string. Also in this case the first part of the cons string is known to be |
| 7653 // a sequential string or an external string. |
| 7654 __ and_(r0, r0, Operand(kStringRepresentationMask)); |
| 7655 __ cmp(r0, Operand(kConsStringTag)); |
| 7656 __ b(ne, &runtime); |
| 7657 __ ldr(r0, FieldMemOperand(subject, ConsString::kSecondOffset)); |
| 7658 __ LoadRoot(r1, Heap::kEmptyStringRootIndex); |
| 7659 __ cmp(r0, r1); |
| 7660 __ b(ne, &runtime); |
| 7661 __ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); |
| 7662 __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset)); |
| 7663 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); |
| 7664 ASSERT_EQ(0, kSeqStringTag); |
| 7665 __ tst(r0, Operand(kStringRepresentationMask)); |
| 7666 __ b(nz, &runtime); |
| 7667 __ and_(r1, r0, Operand(kStringRepresentationEncodingMask)); |
| 7668 |
| 7669 __ bind(&seq_string); |
| 7670 // r1: suject string type & kStringRepresentationEncodingMask |
| 7671 // subject: Subject string |
| 7672 // regexp_data: RegExp data (FixedArray) |
| 7673 // Check that the irregexp code has been generated for an ascii string. If |
| 7674 // it has, the field contains a code object otherwise it contains the hole. |
| 7675 #ifdef DEBUG |
| 7676 const int kSeqAsciiString = kStringTag | kSeqStringTag | kAsciiStringTag; |
| 7677 const int kSeqTwoByteString = kStringTag | kSeqStringTag | kTwoByteStringTag; |
| 7678 CHECK_EQ(4, kSeqAsciiString); |
| 7679 CHECK_EQ(0, kSeqTwoByteString); |
| 7680 #endif |
| 7681 // Find the code object based on the assumptions above. |
| 7682 __ mov(r3, Operand(r1, ASR, 2), SetCC); |
| 7683 __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset), ne); |
| 7684 __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset), eq); |
| 7685 |
| 7686 // Check that the irregexp code has been generated for the actual string |
| 7687 // encoding. If it has, the field contains a code object otherwise it contains |
| 7688 // the hole. |
| 7689 __ CompareObjectType(r7, r0, r0, CODE_TYPE); |
| 7690 __ b(ne, &runtime); |
| 7691 |
| 7692 // r3: encoding of subject string (1 if ascii, 0 if two_byte); |
| 7693 // r7: code |
| 7694 // subject: Subject string |
| 7695 // regexp_data: RegExp data (FixedArray) |
| 7696 // Load used arguments before starting to push arguments for call to native |
| 7697 // RegExp code to avoid handling changing stack height. |
| 7698 __ ldr(r1, MemOperand(sp, kPreviousIndexOffset)); |
| 7699 __ mov(r1, Operand(r1, ASR, kSmiTagSize)); |
| 7700 |
| 7701 // r1: previous index |
| 7702 // r3: encoding of subject string (1 if ascii, 0 if two_byte); |
| 7703 // r7: code |
| 7704 // subject: Subject string |
| 7705 // regexp_data: RegExp data (FixedArray) |
| 7706 // All checks done. Now push arguments for native regexp code. |
| 7707 __ IncrementCounter(&Counters::regexp_entry_native, 1, r0, r2); |
| 7708 |
| 7709 static const int kRegExpExecuteArguments = 7; |
| 7710 __ push(lr); |
| 7711 __ PrepareCallCFunction(kRegExpExecuteArguments, r0); |
| 7712 |
| 7713 // Argument 7 (sp[8]): Indicate that this is a direct call from JavaScript. |
| 7714 __ mov(r0, Operand(1)); |
| 7715 __ str(r0, MemOperand(sp, 2 * kPointerSize)); |
| 7716 |
| 7717 // Argument 6 (sp[4]): Start (high end) of backtracking stack memory area. |
| 7718 __ mov(r0, Operand(address_of_regexp_stack_memory_address)); |
| 7719 __ ldr(r0, MemOperand(r0, 0)); |
| 7720 __ mov(r2, Operand(address_of_regexp_stack_memory_size)); |
| 7721 __ ldr(r2, MemOperand(r2, 0)); |
| 7722 __ add(r0, r0, Operand(r2)); |
| 7723 __ str(r0, MemOperand(sp, 1 * kPointerSize)); |
| 7724 |
| 7725 // Argument 5 (sp[0]): static offsets vector buffer. |
| 7726 __ mov(r0, Operand(ExternalReference::address_of_static_offsets_vector())); |
| 7727 __ str(r0, MemOperand(sp, 0 * kPointerSize)); |
| 7728 |
| 7729 // For arguments 4 and 3 get string length, calculate start of string data and |
| 7730 // calculate the shift of the index (0 for ASCII and 1 for two byte). |
| 7731 __ ldr(r0, FieldMemOperand(subject, String::kLengthOffset)); |
| 7732 ASSERT_EQ(SeqAsciiString::kHeaderSize, SeqTwoByteString::kHeaderSize); |
| 7733 __ add(r9, subject, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
| 7734 __ eor(r3, r3, Operand(1)); |
| 7735 // Argument 4 (r3): End of string data |
| 7736 // Argument 3 (r2): Start of string data |
| 7737 __ add(r2, r9, Operand(r1, LSL, r3)); |
| 7738 __ add(r3, r9, Operand(r0, LSL, r3)); |
| 7739 |
| 7740 // Argument 2 (r1): Previous index. |
| 7741 // Already there |
| 7742 |
| 7743 // Argument 1 (r0): Subject string. |
| 7744 __ mov(r0, subject); |
| 7745 |
| 7746 // Locate the code entry and call it. |
| 7747 __ add(r7, r7, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 7748 __ CallCFunction(r7, kRegExpExecuteArguments); |
| 7749 __ pop(lr); |
| 7750 |
| 7751 // r0: result |
| 7752 // subject: subject string (callee saved) |
| 7753 // regexp_data: RegExp data (callee saved) |
| 7754 // last_match_info_elements: Last match info elements (callee saved) |
| 7755 |
| 7756 // Check the result. |
| 7757 Label success; |
| 7758 __ cmp(r0, Operand(NativeRegExpMacroAssembler::SUCCESS)); |
| 7759 __ b(eq, &success); |
| 7760 Label failure; |
| 7761 __ cmp(r0, Operand(NativeRegExpMacroAssembler::FAILURE)); |
| 7762 __ b(eq, &failure); |
| 7763 __ cmp(r0, Operand(NativeRegExpMacroAssembler::EXCEPTION)); |
| 7764 // If not exception it can only be retry. Handle that in the runtime system. |
| 7765 __ b(ne, &runtime); |
| 7766 // Result must now be exception. If there is no pending exception already a |
| 7767 // stack overflow (on the backtrack stack) was detected in RegExp code but |
| 7768 // haven't created the exception yet. Handle that in the runtime system. |
| 7769 // TODO(592): Rerunning the RegExp to get the stack overflow exception. |
| 7770 __ mov(r0, Operand(ExternalReference::the_hole_value_location())); |
| 7771 __ ldr(r0, MemOperand(r0, 0)); |
| 7772 __ mov(r1, Operand(ExternalReference(Top::k_pending_exception_address))); |
| 7773 __ ldr(r1, MemOperand(r1, 0)); |
| 7774 __ cmp(r0, r1); |
| 7775 __ b(eq, &runtime); |
| 7776 __ bind(&failure); |
| 7777 // For failure and exception return null. |
| 7778 __ mov(r0, Operand(Factory::null_value())); |
| 7779 __ add(sp, sp, Operand(4 * kPointerSize)); |
| 7780 __ Ret(); |
| 7781 |
| 7782 // Process the result from the native regexp code. |
| 7783 __ bind(&success); |
| 7784 __ ldr(r1, |
| 7785 FieldMemOperand(regexp_data, JSRegExp::kIrregexpCaptureCountOffset)); |
| 7786 // Calculate number of capture registers (number_of_captures + 1) * 2. |
| 7787 ASSERT_EQ(0, kSmiTag); |
| 7788 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); |
| 7789 __ add(r1, r1, Operand(2)); // r1 was a smi. |
| 7790 |
| 7791 // r1: number of capture registers |
| 7792 // r4: subject string |
| 7793 // Store the capture count. |
| 7794 __ mov(r2, Operand(r1, LSL, kSmiTagSize + kSmiShiftSize)); // To smi. |
| 7795 __ str(r2, FieldMemOperand(last_match_info_elements, |
| 7796 RegExpImpl::kLastCaptureCountOffset)); |
| 7797 // Store last subject and last input. |
| 7798 __ mov(r3, last_match_info_elements); // Moved up to reduce latency. |
| 7799 __ mov(r2, Operand(RegExpImpl::kLastSubjectOffset)); // Ditto. |
| 7800 __ str(subject, |
| 7801 FieldMemOperand(last_match_info_elements, |
| 7802 RegExpImpl::kLastSubjectOffset)); |
| 7803 __ RecordWrite(r3, r2, r7); |
| 7804 __ str(subject, |
| 7805 FieldMemOperand(last_match_info_elements, |
| 7806 RegExpImpl::kLastInputOffset)); |
| 7807 __ mov(r3, last_match_info_elements); |
| 7808 __ mov(r2, Operand(RegExpImpl::kLastInputOffset)); |
| 7809 __ RecordWrite(r3, r2, r7); |
| 7810 |
| 7811 // Get the static offsets vector filled by the native regexp code. |
| 7812 ExternalReference address_of_static_offsets_vector = |
| 7813 ExternalReference::address_of_static_offsets_vector(); |
| 7814 __ mov(r2, Operand(address_of_static_offsets_vector)); |
| 7815 |
| 7816 // r1: number of capture registers |
| 7817 // r2: offsets vector |
| 7818 Label next_capture, done; |
| 7819 // Capture register counter starts from number of capture registers and |
| 7820 // counts down until wraping after zero. |
| 7821 __ add(r0, |
| 7822 last_match_info_elements, |
| 7823 Operand(RegExpImpl::kFirstCaptureOffset - kHeapObjectTag)); |
| 7824 __ bind(&next_capture); |
| 7825 __ sub(r1, r1, Operand(1), SetCC); |
| 7826 __ b(mi, &done); |
| 7827 // Read the value from the static offsets vector buffer. |
| 7828 __ ldr(r3, MemOperand(r2, kPointerSize, PostIndex)); |
| 7829 // Store the smi value in the last match info. |
| 7830 __ mov(r3, Operand(r3, LSL, kSmiTagSize)); |
| 7831 __ str(r3, MemOperand(r0, kPointerSize, PostIndex)); |
| 7832 __ jmp(&next_capture); |
| 7833 __ bind(&done); |
| 7834 |
| 7835 // Return last match info. |
| 7836 __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset)); |
| 7837 __ add(sp, sp, Operand(4 * kPointerSize)); |
| 7838 __ Ret(); |
| 7839 |
| 7840 // Do the runtime call to execute the regexp. |
| 7841 __ bind(&runtime); |
| 7842 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
| 7843 #endif // V8_NATIVE_REGEXP |
| 7844 } |
| 7845 |
| 7846 |
7505 void CallFunctionStub::Generate(MacroAssembler* masm) { | 7847 void CallFunctionStub::Generate(MacroAssembler* masm) { |
7506 Label slow; | 7848 Label slow; |
7507 | 7849 |
7508 // If the receiver might be a value (string, number or boolean) check for this | 7850 // If the receiver might be a value (string, number or boolean) check for this |
7509 // and box it if it is. | 7851 // and box it if it is. |
7510 if (ReceiverMightBeValue()) { | 7852 if (ReceiverMightBeValue()) { |
7511 // Get the receiver from the stack. | 7853 // Get the receiver from the stack. |
7512 // function, receiver [, arguments] | 7854 // function, receiver [, arguments] |
7513 Label receiver_is_value, receiver_is_js_object; | 7855 Label receiver_is_value, receiver_is_js_object; |
7514 __ ldr(r1, MemOperand(sp, argc_ * kPointerSize)); | 7856 __ ldr(r1, MemOperand(sp, argc_ * kPointerSize)); |
(...skipping 974 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8489 | 8831 |
8490 // Just jump to runtime to add the two strings. | 8832 // Just jump to runtime to add the two strings. |
8491 __ bind(&string_add_runtime); | 8833 __ bind(&string_add_runtime); |
8492 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 8834 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
8493 } | 8835 } |
8494 | 8836 |
8495 | 8837 |
8496 #undef __ | 8838 #undef __ |
8497 | 8839 |
8498 } } // namespace v8::internal | 8840 } } // namespace v8::internal |
OLD | NEW |