Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(339)

Side by Side Diff: src/arm/codegen-arm.cc

Issue 1575035: Port direct call to native RegExp from JavaScript to ARM... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | src/arm/regexp-macro-assembler-arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | src/arm/regexp-macro-assembler-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698