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

Side by Side Diff: src/mips/code-stubs-mips.cc

Issue 7860035: Merge bleeding edge up to 9192 into the GC branch. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/gc
Patch Set: Created 9 years, 3 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 | « src/mips/builtins-mips.cc ('k') | src/mips/constants-mips.h » ('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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 3520 matching lines...) Expand 10 before | Expand all | Expand 10 after
3531 masm->bal(&find_ra); // bal exposes branch delay slot. 3531 masm->bal(&find_ra); // bal exposes branch delay slot.
3532 masm->nop(); // Branch delay slot nop. 3532 masm->nop(); // Branch delay slot nop.
3533 masm->bind(&find_ra); 3533 masm->bind(&find_ra);
3534 3534
3535 // Adjust the value in ra to point to the correct return location, 2nd 3535 // Adjust the value in ra to point to the correct return location, 2nd
3536 // instruction past the real call into C code (the jalr(t9)), and push it. 3536 // instruction past the real call into C code (the jalr(t9)), and push it.
3537 // This is the return address of the exit frame. 3537 // This is the return address of the exit frame.
3538 const int kNumInstructionsToJump = 6; 3538 const int kNumInstructionsToJump = 6;
3539 masm->Addu(ra, ra, kNumInstructionsToJump * kPointerSize); 3539 masm->Addu(ra, ra, kNumInstructionsToJump * kPointerSize);
3540 masm->sw(ra, MemOperand(sp)); // This spot was reserved in EnterExitFrame. 3540 masm->sw(ra, MemOperand(sp)); // This spot was reserved in EnterExitFrame.
3541 masm->Subu(sp, sp, StandardFrameConstants::kCArgsSlotsSize); 3541 masm->Subu(sp, sp, kCArgsSlotsSize);
3542 // Stack is still aligned. 3542 // Stack is still aligned.
3543 3543
3544 // Call the C routine. 3544 // Call the C routine.
3545 masm->mov(t9, s2); // Function pointer to t9 to conform to ABI for PIC. 3545 masm->mov(t9, s2); // Function pointer to t9 to conform to ABI for PIC.
3546 masm->jalr(t9); 3546 masm->jalr(t9);
3547 masm->nop(); // Branch delay slot nop. 3547 masm->nop(); // Branch delay slot nop.
3548 // Make sure the stored 'ra' points to this position. 3548 // Make sure the stored 'ra' points to this position.
3549 ASSERT_EQ(kNumInstructionsToJump, 3549 ASSERT_EQ(kNumInstructionsToJump,
3550 masm->InstructionsGeneratedSince(&find_ra)); 3550 masm->InstructionsGeneratedSince(&find_ra));
3551 } 3551 }
3552 3552
3553 // Restore stack (remove arg slots). 3553 // Restore stack (remove arg slots).
3554 __ Addu(sp, sp, StandardFrameConstants::kCArgsSlotsSize); 3554 __ Addu(sp, sp, kCArgsSlotsSize);
3555 3555
3556 if (always_allocate) { 3556 if (always_allocate) {
3557 // It's okay to clobber a2 and a3 here. v0 & v1 contain result. 3557 // It's okay to clobber a2 and a3 here. v0 & v1 contain result.
3558 __ li(a2, Operand(scope_depth)); 3558 __ li(a2, Operand(scope_depth));
3559 __ lw(a3, MemOperand(a2)); 3559 __ lw(a3, MemOperand(a2));
3560 __ Subu(a3, a3, Operand(1)); 3560 __ Subu(a3, a3, Operand(1));
3561 __ sw(a3, MemOperand(a2)); 3561 __ sw(a3, MemOperand(a2));
3562 } 3562 }
3563 3563
3564 // Check for failure result. 3564 // Check for failure result.
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
3686 // a0: entry address 3686 // a0: entry address
3687 // a1: function 3687 // a1: function
3688 // a2: reveiver 3688 // a2: reveiver
3689 // a3: argc 3689 // a3: argc
3690 // 3690 //
3691 // Stack: 3691 // Stack:
3692 // 4 args slots 3692 // 4 args slots
3693 // args 3693 // args
3694 3694
3695 // Save callee saved registers on the stack. 3695 // Save callee saved registers on the stack.
3696 __ MultiPush((kCalleeSaved | ra.bit()) & ~sp.bit()); 3696 __ MultiPush(kCalleeSaved | ra.bit());
3697
3698 if (CpuFeatures::IsSupported(FPU)) {
3699 CpuFeatures::Scope scope(FPU);
3700 // Save callee-saved FPU registers.
3701 __ MultiPushFPU(kCalleeSavedFPU);
3702 }
3697 3703
3698 // Load argv in s0 register. 3704 // Load argv in s0 register.
3699 __ lw(s0, MemOperand(sp, kNumCalleeSaved * kPointerSize + 3705 int offset_to_argv = (kNumCalleeSaved + 1) * kPointerSize;
3700 StandardFrameConstants::kCArgsSlotsSize)); 3706 if (CpuFeatures::IsSupported(FPU)) {
3707 offset_to_argv += kNumCalleeSavedFPU * kDoubleSize;
3708 }
3709
3710 __ lw(s0, MemOperand(sp, offset_to_argv + kCArgsSlotsSize));
3701 3711
3702 // We build an EntryFrame. 3712 // We build an EntryFrame.
3703 __ li(t3, Operand(-1)); // Push a bad frame pointer to fail if it is used. 3713 __ li(t3, Operand(-1)); // Push a bad frame pointer to fail if it is used.
3704 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; 3714 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
3705 __ li(t2, Operand(Smi::FromInt(marker))); 3715 __ li(t2, Operand(Smi::FromInt(marker)));
3706 __ li(t1, Operand(Smi::FromInt(marker))); 3716 __ li(t1, Operand(Smi::FromInt(marker)));
3707 __ li(t0, Operand(ExternalReference(Isolate::k_c_entry_fp_address, 3717 __ li(t0, Operand(ExternalReference(Isolate::k_c_entry_fp_address,
3708 masm->isolate()))); 3718 masm->isolate())));
3709 __ lw(t0, MemOperand(t0)); 3719 __ lw(t0, MemOperand(t0));
3710 __ Push(t3, t2, t1, t0); 3720 __ Push(t3, t2, t1, t0);
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
3822 3832
3823 // Restore the top frame descriptors from the stack. 3833 // Restore the top frame descriptors from the stack.
3824 __ pop(t1); 3834 __ pop(t1);
3825 __ li(t0, Operand(ExternalReference(Isolate::k_c_entry_fp_address, 3835 __ li(t0, Operand(ExternalReference(Isolate::k_c_entry_fp_address,
3826 masm->isolate()))); 3836 masm->isolate())));
3827 __ sw(t1, MemOperand(t0)); 3837 __ sw(t1, MemOperand(t0));
3828 3838
3829 // Reset the stack to the callee saved registers. 3839 // Reset the stack to the callee saved registers.
3830 __ addiu(sp, sp, -EntryFrameConstants::kCallerFPOffset); 3840 __ addiu(sp, sp, -EntryFrameConstants::kCallerFPOffset);
3831 3841
3842 if (CpuFeatures::IsSupported(FPU)) {
3843 CpuFeatures::Scope scope(FPU);
3844 // Restore callee-saved fpu registers.
3845 __ MultiPopFPU(kCalleeSavedFPU);
3846 }
3847
3832 // Restore callee saved registers from the stack. 3848 // Restore callee saved registers from the stack.
3833 __ MultiPop((kCalleeSaved | ra.bit()) & ~sp.bit()); 3849 __ MultiPop(kCalleeSaved | ra.bit());
3834 // Return. 3850 // Return.
3835 __ Jump(ra); 3851 __ Jump(ra);
3836 } 3852 }
3837 3853
3838 3854
3839 // Uses registers a0 to t0. 3855 // Uses registers a0 to t0.
3840 // Expected input (depending on whether args are in registers or on the stack): 3856 // Expected input (depending on whether args are in registers or on the stack):
3841 // * object: a0 or at sp + 1 * kPointerSize. 3857 // * object: a0 or at sp + 1 * kPointerSize.
3842 // * function: a1 or at sp. 3858 // * function: a1 or at sp.
3843 // 3859 //
(...skipping 666 matching lines...) Expand 10 before | Expand all | Expand 10 after
4510 __ lw(a0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset)); 4526 __ lw(a0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset));
4511 __ Branch(&runtime, ne, a0, Operand( 4527 __ Branch(&runtime, ne, a0, Operand(
4512 masm->isolate()->factory()->fixed_array_map())); 4528 masm->isolate()->factory()->fixed_array_map()));
4513 // Check that the last match info has space for the capture registers and the 4529 // Check that the last match info has space for the capture registers and the
4514 // additional information. 4530 // additional information.
4515 __ lw(a0, 4531 __ lw(a0,
4516 FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset)); 4532 FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset));
4517 __ Addu(a2, a2, Operand(RegExpImpl::kLastMatchOverhead)); 4533 __ Addu(a2, a2, Operand(RegExpImpl::kLastMatchOverhead));
4518 __ sra(at, a0, kSmiTagSize); // Untag length for comparison. 4534 __ sra(at, a0, kSmiTagSize); // Untag length for comparison.
4519 __ Branch(&runtime, gt, a2, Operand(at)); 4535 __ Branch(&runtime, gt, a2, Operand(at));
4536
4537 // Reset offset for possibly sliced string.
4538 __ mov(t0, zero_reg);
4520 // subject: Subject string 4539 // subject: Subject string
4521 // regexp_data: RegExp data (FixedArray) 4540 // regexp_data: RegExp data (FixedArray)
4522 // Check the representation and encoding of the subject string. 4541 // Check the representation and encoding of the subject string.
4523 Label seq_string; 4542 Label seq_string;
4524 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); 4543 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
4525 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); 4544 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
4526 // First check for flat string. 4545 // First check for flat string.
4527 __ And(at, a0, Operand(kIsNotStringMask | kStringRepresentationMask)); 4546 __ And(a1, a0, Operand(kIsNotStringMask | kStringRepresentationMask));
4528 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); 4547 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0);
4529 __ Branch(&seq_string, eq, at, Operand(zero_reg)); 4548 __ Branch(&seq_string, eq, a1, Operand(zero_reg));
4530 4549
4531 // subject: Subject string 4550 // subject: Subject string
4532 // a0: instance type if Subject string 4551 // a0: instance type if Subject string
4533 // regexp_data: RegExp data (FixedArray) 4552 // regexp_data: RegExp data (FixedArray)
4534 // Check for flat cons string. 4553 // Check for flat cons string or sliced string.
4535 // A flat cons string is a cons string where the second part is the empty 4554 // A flat cons string is a cons string where the second part is the empty
4536 // string. In that case the subject string is just the first part of the cons 4555 // string. In that case the subject string is just the first part of the cons
4537 // string. Also in this case the first part of the cons string is known to be 4556 // string. Also in this case the first part of the cons string is known to be
4538 // a sequential string or an external string. 4557 // a sequential string or an external string.
4539 STATIC_ASSERT(kExternalStringTag != 0); 4558 // In the case of a sliced string its offset has to be taken into account.
4540 STATIC_ASSERT((kConsStringTag & kExternalStringTag) == 0); 4559 Label cons_string, check_encoding;
4541 __ And(at, a0, Operand(kIsNotStringMask | kExternalStringTag)); 4560 STATIC_ASSERT(kConsStringTag < kExternalStringTag);
4542 __ Branch(&runtime, ne, at, Operand(zero_reg)); 4561 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
4562 __ Branch(&cons_string, lt, a1, Operand(kExternalStringTag));
4563 __ Branch(&runtime, eq, a1, Operand(kExternalStringTag));
4564
4565 // String is sliced.
4566 __ lw(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset));
4567 __ sra(t0, t0, kSmiTagSize);
4568 __ lw(subject, FieldMemOperand(subject, SlicedString::kParentOffset));
4569 // t5: offset of sliced string, smi-tagged.
4570 __ jmp(&check_encoding);
4571 // String is a cons string, check whether it is flat.
4572 __ bind(&cons_string);
4543 __ lw(a0, FieldMemOperand(subject, ConsString::kSecondOffset)); 4573 __ lw(a0, FieldMemOperand(subject, ConsString::kSecondOffset));
4544 __ LoadRoot(a1, Heap::kEmptyStringRootIndex); 4574 __ LoadRoot(a1, Heap::kEmptyStringRootIndex);
4545 __ Branch(&runtime, ne, a0, Operand(a1)); 4575 __ Branch(&runtime, ne, a0, Operand(a1));
4546 __ lw(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); 4576 __ lw(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
4577 // Is first part of cons or parent of slice a flat string?
4578 __ bind(&check_encoding);
4547 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); 4579 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset));
4548 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); 4580 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
4549 // Is first part a flat string?
4550 STATIC_ASSERT(kSeqStringTag == 0); 4581 STATIC_ASSERT(kSeqStringTag == 0);
4551 __ And(at, a0, Operand(kStringRepresentationMask)); 4582 __ And(at, a0, Operand(kStringRepresentationMask));
4552 __ Branch(&runtime, ne, at, Operand(zero_reg)); 4583 __ Branch(&runtime, ne, at, Operand(zero_reg));
4553 4584
4554 __ bind(&seq_string); 4585 __ bind(&seq_string);
4555 // subject: Subject string 4586 // subject: Subject string
4556 // regexp_data: RegExp data (FixedArray) 4587 // regexp_data: RegExp data (FixedArray)
4557 // a0: Instance type of subject string 4588 // a0: Instance type of subject string
4558 STATIC_ASSERT(kStringEncodingMask == 4); 4589 STATIC_ASSERT(kStringEncodingMask == 4);
4559 STATIC_ASSERT(kAsciiStringTag == 4); 4590 STATIC_ASSERT(kAsciiStringTag == 4);
4560 STATIC_ASSERT(kTwoByteStringTag == 0); 4591 STATIC_ASSERT(kTwoByteStringTag == 0);
4561 // Find the code object based on the assumptions above. 4592 // Find the code object based on the assumptions above.
4562 __ And(a0, a0, Operand(kStringEncodingMask)); // Non-zero for ascii. 4593 __ And(a0, a0, Operand(kStringEncodingMask)); // Non-zero for ascii.
4563 __ lw(t9, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset)); 4594 __ lw(t9, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset));
4564 __ sra(a3, a0, 2); // a3 is 1 for ascii, 0 for UC16 (usyed below). 4595 __ sra(a3, a0, 2); // a3 is 1 for ascii, 0 for UC16 (usyed below).
4565 __ lw(t0, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset)); 4596 __ lw(t1, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset));
4566 __ movz(t9, t0, a0); // If UC16 (a0 is 0), replace t9 w/kDataUC16CodeOffset. 4597 __ movz(t9, t1, a0); // If UC16 (a0 is 0), replace t9 w/kDataUC16CodeOffset.
4567 4598
4568 // Check that the irregexp code has been generated for the actual string 4599 // Check that the irregexp code has been generated for the actual string
4569 // encoding. If it has, the field contains a code object otherwise it contains 4600 // encoding. If it has, the field contains a code object otherwise it contains
4570 // a smi (code flushing support). 4601 // a smi (code flushing support).
4571 __ JumpIfSmi(t9, &runtime); 4602 __ JumpIfSmi(t9, &runtime);
4572 4603
4573 // a3: encoding of subject string (1 if ASCII, 0 if two_byte); 4604 // a3: encoding of subject string (1 if ASCII, 0 if two_byte);
4574 // t9: code 4605 // t9: code
4575 // subject: Subject string 4606 // subject: Subject string
4576 // regexp_data: RegExp data (FixedArray) 4607 // regexp_data: RegExp data (FixedArray)
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
4623 __ addu(a0, a0, a2); 4654 __ addu(a0, a0, a2);
4624 __ sw(a0, MemOperand(sp, 2 * kPointerSize)); 4655 __ sw(a0, MemOperand(sp, 2 * kPointerSize));
4625 4656
4626 // Argument 5: static offsets vector buffer. 4657 // Argument 5: static offsets vector buffer.
4627 __ li(a0, Operand( 4658 __ li(a0, Operand(
4628 ExternalReference::address_of_static_offsets_vector(masm->isolate()))); 4659 ExternalReference::address_of_static_offsets_vector(masm->isolate())));
4629 __ sw(a0, MemOperand(sp, 1 * kPointerSize)); 4660 __ sw(a0, MemOperand(sp, 1 * kPointerSize));
4630 4661
4631 // For arguments 4 and 3 get string length, calculate start of string data 4662 // For arguments 4 and 3 get string length, calculate start of string data
4632 // and calculate the shift of the index (0 for ASCII and 1 for two byte). 4663 // and calculate the shift of the index (0 for ASCII and 1 for two byte).
4633 __ lw(a0, FieldMemOperand(subject, String::kLengthOffset));
4634 __ sra(a0, a0, kSmiTagSize);
4635 STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize); 4664 STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize);
4636 __ Addu(t0, subject, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 4665 __ Addu(t2, subject, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
4637 __ Xor(a3, a3, Operand(1)); // 1 for 2-byte str, 0 for 1-byte. 4666 __ Xor(a3, a3, Operand(1)); // 1 for 2-byte str, 0 for 1-byte.
4638 // Argument 4 (a3): End of string data 4667 // Load the length from the original subject string from the previous stack
4639 // Argument 3 (a2): Start of string data 4668 // frame. Therefore we have to use fp, which points exactly to two pointer
4669 // sizes below the previous sp. (Because creating a new stack frame pushes
4670 // the previous fp onto the stack and moves up sp by 2 * kPointerSize.)
4671 __ lw(subject, MemOperand(fp, kSubjectOffset + 2 * kPointerSize));
4672 // If slice offset is not 0, load the length from the original sliced string.
4673 // Argument 4, a3: End of string data
4674 // Argument 3, a2: Start of string data
4675 // Prepare start and end index of the input.
4676 __ sllv(t1, t0, a3);
4677 __ addu(t0, t2, t1);
4640 __ sllv(t1, a1, a3); 4678 __ sllv(t1, a1, a3);
4641 __ addu(a2, t0, t1); 4679 __ addu(a2, t0, t1);
4642 __ sllv(t1, a0, a3); 4680
4681 __ lw(t2, FieldMemOperand(subject, String::kLengthOffset));
4682 __ sra(t2, t2, kSmiTagSize);
4683 __ sllv(t1, t2, a3);
4643 __ addu(a3, t0, t1); 4684 __ addu(a3, t0, t1);
4644
4645 // Argument 2 (a1): Previous index. 4685 // Argument 2 (a1): Previous index.
4646 // Already there 4686 // Already there
4647 4687
4648 // Argument 1 (a0): Subject string. 4688 // Argument 1 (a0): Subject string.
4649 __ mov(a0, subject); 4689 __ mov(a0, subject);
4650 4690
4651 // Locate the code entry and call it. 4691 // Locate the code entry and call it.
4652 __ Addu(t9, t9, Operand(Code::kHeaderSize - kHeapObjectTag)); 4692 __ Addu(t9, t9, Operand(Code::kHeaderSize - kHeapObjectTag));
4653 DirectCEntryStub stub; 4693 DirectCEntryStub stub;
4654 stub.GenerateCall(masm, t9); 4694 stub.GenerateCall(masm, t9);
4655 4695
4656 __ LeaveExitFrame(false, no_reg); 4696 __ LeaveExitFrame(false, no_reg);
4657 4697
4658 // v0: result 4698 // v0: result
4659 // subject: subject string (callee saved) 4699 // subject: subject string (callee saved)
4660 // regexp_data: RegExp data (callee saved) 4700 // regexp_data: RegExp data (callee saved)
4661 // last_match_info_elements: Last match info elements (callee saved) 4701 // last_match_info_elements: Last match info elements (callee saved)
4662 4702
4663 // Check the result. 4703 // Check the result.
4664 4704
4665 Label success; 4705 Label success;
4666 __ Branch(&success, eq, v0, Operand(NativeRegExpMacroAssembler::SUCCESS)); 4706 __ Branch(&success, eq,
4707 v0, Operand(NativeRegExpMacroAssembler::SUCCESS));
4667 Label failure; 4708 Label failure;
4668 __ Branch(&failure, eq, v0, Operand(NativeRegExpMacroAssembler::FAILURE)); 4709 __ Branch(&failure, eq,
4710 v0, Operand(NativeRegExpMacroAssembler::FAILURE));
4669 // If not exception it can only be retry. Handle that in the runtime system. 4711 // If not exception it can only be retry. Handle that in the runtime system.
4670 __ Branch(&runtime, ne, v0, Operand(NativeRegExpMacroAssembler::EXCEPTION)); 4712 __ Branch(&runtime, ne,
4713 v0, Operand(NativeRegExpMacroAssembler::EXCEPTION));
4671 // Result must now be exception. If there is no pending exception already a 4714 // Result must now be exception. If there is no pending exception already a
4672 // stack overflow (on the backtrack stack) was detected in RegExp code but 4715 // stack overflow (on the backtrack stack) was detected in RegExp code but
4673 // haven't created the exception yet. Handle that in the runtime system. 4716 // haven't created the exception yet. Handle that in the runtime system.
4674 // TODO(592): Rerunning the RegExp to get the stack overflow exception. 4717 // TODO(592): Rerunning the RegExp to get the stack overflow exception.
4675 __ li(a1, Operand( 4718 __ li(a1, Operand(
4676 ExternalReference::the_hole_value_location(masm->isolate()))); 4719 ExternalReference::the_hole_value_location(masm->isolate())));
4677 __ lw(a1, MemOperand(a1, 0)); 4720 __ lw(a1, MemOperand(a1, 0));
4678 __ li(a2, Operand(ExternalReference(Isolate::k_pending_exception_address, 4721 __ li(a2, Operand(ExternalReference(Isolate::k_pending_exception_address,
4679 masm->isolate()))); 4722 masm->isolate())));
4680 __ lw(v0, MemOperand(a2, 0)); 4723 __ lw(v0, MemOperand(a2, 0));
4681 __ Branch(&runtime, eq, v0, Operand(a1)); 4724 __ Branch(&runtime, eq, v0, Operand(a1));
4682 4725
4683 __ sw(a1, MemOperand(a2, 0)); // Clear pending exception. 4726 __ sw(a1, MemOperand(a2, 0)); // Clear pending exception.
4684 4727
4685 // Check if the exception is a termination. If so, throw as uncatchable. 4728 // Check if the exception is a termination. If so, throw as uncatchable.
4686 __ LoadRoot(a0, Heap::kTerminationExceptionRootIndex); 4729 __ LoadRoot(a0, Heap::kTerminationExceptionRootIndex);
4687 Label termination_exception; 4730 Label termination_exception;
4688 __ Branch(&termination_exception, eq, v0, Operand(a0)); 4731 __ Branch(&termination_exception, eq, v0, Operand(a0));
4689 4732
4690 __ Throw(a0); // Expects thrown value in v0. 4733 __ Throw(v0); // Expects thrown value in v0.
4691 4734
4692 __ bind(&termination_exception); 4735 __ bind(&termination_exception);
4693 __ ThrowUncatchable(TERMINATION, v0); // Expects thrown value in v0. 4736 __ ThrowUncatchable(TERMINATION, v0); // Expects thrown value in v0.
4694 4737
4695 __ bind(&failure); 4738 __ bind(&failure);
4696 // For failure and exception return null. 4739 // For failure and exception return null.
4697 __ li(v0, Operand(masm->isolate()->factory()->null_value())); 4740 __ li(v0, Operand(masm->isolate()->factory()->null_value()));
4698 __ Addu(sp, sp, Operand(4 * kPointerSize)); 4741 __ Addu(sp, sp, Operand(4 * kPointerSize));
4699 __ Ret(); 4742 __ Ret();
4700 4743
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
4956 | NeverNanNanField::encode(cc_ == eq ? never_nan_nan_ : false) 4999 | NeverNanNanField::encode(cc_ == eq ? never_nan_nan_ : false)
4957 | IncludeSmiCompareField::encode(include_smi_compare_); 5000 | IncludeSmiCompareField::encode(include_smi_compare_);
4958 } 5001 }
4959 5002
4960 5003
4961 // StringCharCodeAtGenerator. 5004 // StringCharCodeAtGenerator.
4962 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { 5005 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
4963 Label flat_string; 5006 Label flat_string;
4964 Label ascii_string; 5007 Label ascii_string;
4965 Label got_char_code; 5008 Label got_char_code;
5009 Label sliced_string;
4966 5010
4967 ASSERT(!t0.is(scratch_)); 5011 ASSERT(!t0.is(scratch_));
4968 ASSERT(!t0.is(index_)); 5012 ASSERT(!t0.is(index_));
4969 ASSERT(!t0.is(result_)); 5013 ASSERT(!t0.is(result_));
4970 ASSERT(!t0.is(object_)); 5014 ASSERT(!t0.is(object_));
4971 5015
4972 // If the receiver is a smi trigger the non-string case. 5016 // If the receiver is a smi trigger the non-string case.
4973 __ JumpIfSmi(object_, receiver_not_string_); 5017 __ JumpIfSmi(object_, receiver_not_string_);
4974 5018
4975 // Fetch the instance type of the receiver into result register. 5019 // Fetch the instance type of the receiver into result register.
(...skipping 13 matching lines...) Expand all
4989 // Check for index out of range. 5033 // Check for index out of range.
4990 __ lw(t0, FieldMemOperand(object_, String::kLengthOffset)); 5034 __ lw(t0, FieldMemOperand(object_, String::kLengthOffset));
4991 __ Branch(index_out_of_range_, ls, t0, Operand(scratch_)); 5035 __ Branch(index_out_of_range_, ls, t0, Operand(scratch_));
4992 5036
4993 // We need special handling for non-flat strings. 5037 // We need special handling for non-flat strings.
4994 STATIC_ASSERT(kSeqStringTag == 0); 5038 STATIC_ASSERT(kSeqStringTag == 0);
4995 __ And(t0, result_, Operand(kStringRepresentationMask)); 5039 __ And(t0, result_, Operand(kStringRepresentationMask));
4996 __ Branch(&flat_string, eq, t0, Operand(zero_reg)); 5040 __ Branch(&flat_string, eq, t0, Operand(zero_reg));
4997 5041
4998 // Handle non-flat strings. 5042 // Handle non-flat strings.
4999 __ And(t0, result_, Operand(kIsConsStringMask)); 5043 __ And(result_, result_, Operand(kStringRepresentationMask));
5000 __ Branch(&call_runtime_, eq, t0, Operand(zero_reg)); 5044 STATIC_ASSERT(kConsStringTag < kExternalStringTag);
5045 STATIC_ASSERT(kSlicedStringTag > kExternalStringTag);
5046 __ Branch(&sliced_string, gt, result_, Operand(kExternalStringTag));
5047 __ Branch(&call_runtime_, eq, result_, Operand(kExternalStringTag));
5001 5048
5002 // ConsString. 5049 // ConsString.
5003 // Check whether the right hand side is the empty string (i.e. if 5050 // Check whether the right hand side is the empty string (i.e. if
5004 // this is really a flat string in a cons string). If that is not 5051 // this is really a flat string in a cons string). If that is not
5005 // the case we would rather go to the runtime system now to flatten 5052 // the case we would rather go to the runtime system now to flatten
5006 // the string. 5053 // the string.
5054 Label assure_seq_string;
5007 __ lw(result_, FieldMemOperand(object_, ConsString::kSecondOffset)); 5055 __ lw(result_, FieldMemOperand(object_, ConsString::kSecondOffset));
5008 __ LoadRoot(t0, Heap::kEmptyStringRootIndex); 5056 __ LoadRoot(t0, Heap::kEmptyStringRootIndex);
5009 __ Branch(&call_runtime_, ne, result_, Operand(t0)); 5057 __ Branch(&call_runtime_, ne, result_, Operand(t0));
5010 5058
5011 // Get the first of the two strings and load its instance type. 5059 // Get the first of the two strings and load its instance type.
5012 __ lw(object_, FieldMemOperand(object_, ConsString::kFirstOffset)); 5060 __ lw(object_, FieldMemOperand(object_, ConsString::kFirstOffset));
5061 __ jmp(&assure_seq_string);
5062
5063 // SlicedString, unpack and add offset.
5064 __ bind(&sliced_string);
5065 __ lw(result_, FieldMemOperand(object_, SlicedString::kOffsetOffset));
5066 __ addu(scratch_, scratch_, result_);
5067 __ lw(object_, FieldMemOperand(object_, SlicedString::kParentOffset));
5068
5069 // Assure that we are dealing with a sequential string. Go to runtime if not.
5070 __ bind(&assure_seq_string);
5013 __ lw(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); 5071 __ lw(result_, FieldMemOperand(object_, HeapObject::kMapOffset));
5014 __ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); 5072 __ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset));
5015 // If the first cons component is also non-flat, then go to runtime. 5073 // Check that parent is not an external string. Go to runtime otherwise.
5016 STATIC_ASSERT(kSeqStringTag == 0); 5074 STATIC_ASSERT(kSeqStringTag == 0);
5017 5075
5018 __ And(t0, result_, Operand(kStringRepresentationMask)); 5076 __ And(t0, result_, Operand(kStringRepresentationMask));
5019 __ Branch(&call_runtime_, ne, t0, Operand(zero_reg)); 5077 __ Branch(&call_runtime_, ne, t0, Operand(zero_reg));
5020 5078
5021 // Check for 1-byte or 2-byte string. 5079 // Check for 1-byte or 2-byte string.
5022 __ bind(&flat_string); 5080 __ bind(&flat_string);
5023 STATIC_ASSERT(kAsciiStringTag != 0); 5081 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
5082 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
5024 __ And(t0, result_, Operand(kStringEncodingMask)); 5083 __ And(t0, result_, Operand(kStringEncodingMask));
5025 __ Branch(&ascii_string, ne, t0, Operand(zero_reg)); 5084 __ Branch(&ascii_string, ne, t0, Operand(zero_reg));
5026 5085
5027 // 2-byte string. 5086 // 2-byte string.
5028 // Load the 2-byte character code into the result register. We can 5087 // Load the 2-byte character code into the result register. We can
5029 // add without shifting since the smi tag size is the log2 of the 5088 // add without shifting since the smi tag size is the log2 of the
5030 // number of bytes in a two-byte character. 5089 // number of bytes in a two-byte character.
5031 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1 && kSmiShiftSize == 0); 5090 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1 && kSmiShiftSize == 0);
5032 __ Addu(scratch_, object_, Operand(scratch_)); 5091 __ Addu(scratch_, object_, Operand(scratch_));
5033 __ lhu(result_, FieldMemOperand(scratch_, SeqTwoByteString::kHeaderSize)); 5092 __ lhu(result_, FieldMemOperand(scratch_, SeqTwoByteString::kHeaderSize));
(...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after
5599 // a3: from index (untagged smi) 5658 // a3: from index (untagged smi)
5600 // t5: to index (untagged smi) 5659 // t5: to index (untagged smi)
5601 5660
5602 __ Branch(&sub_string_runtime, lt, a3, Operand(zero_reg)); // From < 0. 5661 __ Branch(&sub_string_runtime, lt, a3, Operand(zero_reg)); // From < 0.
5603 5662
5604 __ subu(a2, t5, a3); 5663 __ subu(a2, t5, a3);
5605 __ Branch(&sub_string_runtime, gt, a3, Operand(t5)); // Fail if from > to. 5664 __ Branch(&sub_string_runtime, gt, a3, Operand(t5)); // Fail if from > to.
5606 5665
5607 // Special handling of sub-strings of length 1 and 2. One character strings 5666 // Special handling of sub-strings of length 1 and 2. One character strings
5608 // are handled in the runtime system (looked up in the single character 5667 // are handled in the runtime system (looked up in the single character
5609 // cache). Two character strings are looked for in the symbol cache. 5668 // cache). Two character strings are looked for in the symbol cache in
5669 // generated code.
5610 __ Branch(&sub_string_runtime, lt, a2, Operand(2)); 5670 __ Branch(&sub_string_runtime, lt, a2, Operand(2));
5611 5671
5612 // Both to and from are smis. 5672 // Both to and from are smis.
5613 5673
5614 // a2: result string length 5674 // a2: result string length
5615 // a3: from index (untagged smi) 5675 // a3: from index (untagged smi)
5616 // t2: (a.k.a. to): to (smi) 5676 // t2: (a.k.a. to): to (smi)
5617 // t3: (a.k.a. from): from offset (smi) 5677 // t3: (a.k.a. from): from offset (smi)
5618 // t5: to index (untagged smi) 5678 // t5: to index (untagged smi)
5619 5679
5620 // Make sure first argument is a sequential (or flat) string. 5680 // Make sure first argument is a sequential (or flat) string.
5621 __ lw(t1, MemOperand(sp, kStringOffset)); 5681 __ lw(v0, MemOperand(sp, kStringOffset));
5622 __ Branch(&sub_string_runtime, eq, t1, Operand(kSmiTagMask)); 5682 __ Branch(&sub_string_runtime, eq, v0, Operand(kSmiTagMask));
5623 5683
5624 __ lw(a1, FieldMemOperand(t1, HeapObject::kMapOffset)); 5684 __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
5625 __ lbu(a1, FieldMemOperand(a1, Map::kInstanceTypeOffset)); 5685 __ lbu(a1, FieldMemOperand(a1, Map::kInstanceTypeOffset));
5626 __ And(t4, a1, Operand(kIsNotStringMask)); 5686 __ And(t4, v0, Operand(kIsNotStringMask));
5627 5687
5628 __ Branch(&sub_string_runtime, ne, t4, Operand(zero_reg)); 5688 __ Branch(&sub_string_runtime, ne, t4, Operand(zero_reg));
5629 5689
5690 // Short-cut for the case of trivial substring.
5691 Label return_v0;
5692 // v0: original string
5693 // a2: result string length
5694 __ lw(t0, FieldMemOperand(v0, String::kLengthOffset));
5695 __ sra(t0, t0, 1);
5696 __ Branch(&return_v0, eq, a2, Operand(t0));
5697
5698 Label create_slice;
5699 if (FLAG_string_slices) {
5700 __ Branch(&create_slice, ge, a2, Operand(SlicedString::kMinLength));
5701 }
5702
5703 // v0: original string
5630 // a1: instance type 5704 // a1: instance type
5631 // a2: result string length 5705 // a2: result string length
5632 // a3: from index (untagged smi) 5706 // a3: from index (untagged smi)
5633 // t1: string
5634 // t2: (a.k.a. to): to (smi) 5707 // t2: (a.k.a. to): to (smi)
5635 // t3: (a.k.a. from): from offset (smi) 5708 // t3: (a.k.a. from): from offset (smi)
5636 // t5: to index (untagged smi) 5709 // t5: to index (untagged smi)
5637 5710
5638 Label seq_string; 5711 Label seq_string;
5639 __ And(t0, a1, Operand(kStringRepresentationMask)); 5712 __ And(t0, a1, Operand(kStringRepresentationMask));
5640 STATIC_ASSERT(kSeqStringTag < kConsStringTag); 5713 STATIC_ASSERT(kSeqStringTag < kConsStringTag);
5641 STATIC_ASSERT(kConsStringTag < kExternalStringTag); 5714 STATIC_ASSERT(kConsStringTag < kExternalStringTag);
5715 STATIC_ASSERT(kConsStringTag < kSlicedStringTag);
5642 5716
5643 // External strings go to runtime. 5717 // Slices and external strings go to runtime.
5644 __ Branch(&sub_string_runtime, gt, t0, Operand(kConsStringTag)); 5718 __ Branch(&sub_string_runtime, gt, t0, Operand(kConsStringTag));
5645 5719
5646 // Sequential strings are handled directly. 5720 // Sequential strings are handled directly.
5647 __ Branch(&seq_string, lt, t0, Operand(kConsStringTag)); 5721 __ Branch(&seq_string, lt, t0, Operand(kConsStringTag));
5648 5722
5649 // Cons string. Try to recurse (once) on the first substring. 5723 // Cons string. Try to recurse (once) on the first substring.
5650 // (This adds a little more generality than necessary to handle flattened 5724 // (This adds a little more generality than necessary to handle flattened
5651 // cons strings, but not much). 5725 // cons strings, but not much).
5652 __ lw(t1, FieldMemOperand(t1, ConsString::kFirstOffset)); 5726 __ lw(v0, FieldMemOperand(v0, ConsString::kFirstOffset));
5653 __ lw(t0, FieldMemOperand(t1, HeapObject::kMapOffset)); 5727 __ lw(t0, FieldMemOperand(v0, HeapObject::kMapOffset));
5654 __ lbu(a1, FieldMemOperand(t0, Map::kInstanceTypeOffset)); 5728 __ lbu(a1, FieldMemOperand(t0, Map::kInstanceTypeOffset));
5655 STATIC_ASSERT(kSeqStringTag == 0); 5729 STATIC_ASSERT(kSeqStringTag == 0);
5656 // Cons and External strings go to runtime. 5730 // Cons, slices and external strings go to runtime.
5657 __ Branch(&sub_string_runtime, ne, a1, Operand(kStringRepresentationMask)); 5731 __ Branch(&sub_string_runtime, ne, a1, Operand(kStringRepresentationMask));
5658 5732
5659 // Definitly a sequential string. 5733 // Definitly a sequential string.
5660 __ bind(&seq_string); 5734 __ bind(&seq_string);
5661 5735
5736 // v0: original string
5662 // a1: instance type 5737 // a1: instance type
5663 // a2: result string length 5738 // a2: result string length
5664 // a3: from index (untagged smi) 5739 // a3: from index (untagged smi)
5665 // t1: string
5666 // t2: (a.k.a. to): to (smi) 5740 // t2: (a.k.a. to): to (smi)
5667 // t3: (a.k.a. from): from offset (smi) 5741 // t3: (a.k.a. from): from offset (smi)
5668 // t5: to index (untagged smi) 5742 // t5: to index (untagged smi)
5669 5743
5670 __ lw(t0, FieldMemOperand(t1, String::kLengthOffset)); 5744 __ lw(t0, FieldMemOperand(v0, String::kLengthOffset));
5671 __ Branch(&sub_string_runtime, lt, t0, Operand(to)); // Fail if to > length. 5745 __ Branch(&sub_string_runtime, lt, t0, Operand(to)); // Fail if to > length.
5672 to = no_reg; 5746 to = no_reg;
5673 5747
5748 // v0: original string or left hand side of the original cons string.
5674 // a1: instance type 5749 // a1: instance type
5675 // a2: result string length 5750 // a2: result string length
5676 // a3: from index (untagged smi) 5751 // a3: from index (untagged smi)
5677 // t1: string
5678 // t3: (a.k.a. from): from offset (smi) 5752 // t3: (a.k.a. from): from offset (smi)
5679 // t5: to index (untagged smi) 5753 // t5: to index (untagged smi)
5680 5754
5681 // Check for flat ASCII string. 5755 // Check for flat ASCII string.
5682 Label non_ascii_flat; 5756 Label non_ascii_flat;
5683 STATIC_ASSERT(kTwoByteStringTag == 0); 5757 STATIC_ASSERT(kTwoByteStringTag == 0);
5684 5758
5685 __ And(t4, a1, Operand(kStringEncodingMask)); 5759 __ And(t4, a1, Operand(kStringEncodingMask));
5686 __ Branch(&non_ascii_flat, eq, t4, Operand(zero_reg)); 5760 __ Branch(&non_ascii_flat, eq, t4, Operand(zero_reg));
5687 5761
5688 Label result_longer_than_two; 5762 Label result_longer_than_two;
5689 __ Branch(&result_longer_than_two, gt, a2, Operand(2)); 5763 __ Branch(&result_longer_than_two, gt, a2, Operand(2));
5690 5764
5691 // Sub string of length 2 requested. 5765 // Sub string of length 2 requested.
5692 // Get the two characters forming the sub string. 5766 // Get the two characters forming the sub string.
5693 __ Addu(t1, t1, Operand(a3)); 5767 __ Addu(v0, v0, Operand(a3));
5694 __ lbu(a3, FieldMemOperand(t1, SeqAsciiString::kHeaderSize)); 5768 __ lbu(a3, FieldMemOperand(v0, SeqAsciiString::kHeaderSize));
5695 __ lbu(t0, FieldMemOperand(t1, SeqAsciiString::kHeaderSize + 1)); 5769 __ lbu(t0, FieldMemOperand(v0, SeqAsciiString::kHeaderSize + 1));
5696 5770
5697 // Try to lookup two character string in symbol table. 5771 // Try to lookup two character string in symbol table.
5698 Label make_two_character_string; 5772 Label make_two_character_string;
5699 StringHelper::GenerateTwoCharacterSymbolTableProbe( 5773 StringHelper::GenerateTwoCharacterSymbolTableProbe(
5700 masm, a3, t0, a1, t1, t2, t3, t4, &make_two_character_string); 5774 masm, a3, t0, a1, t1, t2, t3, t4, &make_two_character_string);
5701 Counters* counters = masm->isolate()->counters(); 5775 Counters* counters = masm->isolate()->counters();
5702 __ IncrementCounter(counters->sub_string_native(), 1, a3, t0); 5776 __ jmp(&return_v0);
5703 __ Addu(sp, sp, Operand(3 * kPointerSize));
5704 __ Ret();
5705
5706 5777
5707 // a2: result string length. 5778 // a2: result string length.
5708 // a3: two characters combined into halfword in little endian byte order. 5779 // a3: two characters combined into halfword in little endian byte order.
5709 __ bind(&make_two_character_string); 5780 __ bind(&make_two_character_string);
5710 __ AllocateAsciiString(v0, a2, t0, t1, t4, &sub_string_runtime); 5781 __ AllocateAsciiString(v0, a2, t0, t1, t4, &sub_string_runtime);
5711 __ sh(a3, FieldMemOperand(v0, SeqAsciiString::kHeaderSize)); 5782 __ sh(a3, FieldMemOperand(v0, SeqAsciiString::kHeaderSize));
5712 __ IncrementCounter(counters->sub_string_native(), 1, a3, t0); 5783 __ jmp(&return_v0);
5713 __ Addu(sp, sp, Operand(3 * kPointerSize));
5714 __ Ret();
5715 5784
5716 __ bind(&result_longer_than_two); 5785 __ bind(&result_longer_than_two);
5717 5786
5787 // Locate 'from' character of string.
5788 __ Addu(t1, v0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
5789 __ sra(t4, from, 1);
5790 __ Addu(t1, t1, t4);
5791
5718 // Allocate the result. 5792 // Allocate the result.
5719 __ AllocateAsciiString(v0, a2, t4, t0, a1, &sub_string_runtime); 5793 __ AllocateAsciiString(v0, a2, t4, t0, a1, &sub_string_runtime);
5720 5794
5721 // v0: result string. 5795 // v0: result string
5722 // a2: result string length. 5796 // a2: result string length
5723 // a3: from index (untagged smi) 5797 // a3: from index (untagged smi)
5724 // t1: string. 5798 // t1: first character of substring to copy
5725 // t3: (a.k.a. from): from offset (smi) 5799 // t3: (a.k.a. from): from offset (smi)
5726 // Locate first character of result. 5800 // Locate first character of result.
5727 __ Addu(a1, v0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 5801 __ Addu(a1, v0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
5728 // Locate 'from' character of string.
5729 __ Addu(t1, t1, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
5730 __ Addu(t1, t1, Operand(a3));
5731 5802
5732 // v0: result string. 5803 // v0: result string
5733 // a1: first character of result string. 5804 // a1: first character of result string
5734 // a2: result string length. 5805 // a2: result string length
5735 // t1: first character of sub string to copy. 5806 // t1: first character of substring to copy
5736 STATIC_ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0); 5807 STATIC_ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0);
5737 StringHelper::GenerateCopyCharactersLong( 5808 StringHelper::GenerateCopyCharactersLong(
5738 masm, a1, t1, a2, a3, t0, t2, t3, t4, COPY_ASCII | DEST_ALWAYS_ALIGNED); 5809 masm, a1, t1, a2, a3, t0, t2, t3, t4, COPY_ASCII | DEST_ALWAYS_ALIGNED);
5739 __ IncrementCounter(counters->sub_string_native(), 1, a3, t0); 5810 __ jmp(&return_v0);
5740 __ Addu(sp, sp, Operand(3 * kPointerSize));
5741 __ Ret();
5742 5811
5743 __ bind(&non_ascii_flat); 5812 __ bind(&non_ascii_flat);
5744 // a2: result string length. 5813 // a2: result string length
5745 // t1: string. 5814 // t1: string
5746 // t3: (a.k.a. from): from offset (smi) 5815 // t3: (a.k.a. from): from offset (smi)
5747 // Check for flat two byte string. 5816 // Check for flat two byte string.
5748 5817
5818 // Locate 'from' character of string.
5819 __ Addu(t1, v0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
5820 // As "from" is a smi it is 2 times the value which matches the size of a two
5821 // byte character.
5822 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
5823 __ Addu(t1, t1, Operand(from));
5824
5749 // Allocate the result. 5825 // Allocate the result.
5750 __ AllocateTwoByteString(v0, a2, a1, a3, t0, &sub_string_runtime); 5826 __ AllocateTwoByteString(v0, a2, a1, a3, t0, &sub_string_runtime);
5751 5827
5752 // v0: result string. 5828 // v0: result string
5753 // a2: result string length. 5829 // a2: result string length
5754 // t1: string. 5830 // t1: first character of substring to copy
5755 // Locate first character of result. 5831 // Locate first character of result.
5756 __ Addu(a1, v0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 5832 __ Addu(a1, v0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
5757 // Locate 'from' character of string. 5833
5758 __ Addu(t1, t1, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
5759 // As "from" is a smi it is 2 times the value which matches the size of a two
5760 // byte character.
5761 __ Addu(t1, t1, Operand(from));
5762 from = no_reg; 5834 from = no_reg;
5763 5835
5764 // v0: result string. 5836 // v0: result string.
5765 // a1: first character of result. 5837 // a1: first character of result.
5766 // a2: result length. 5838 // a2: result length.
5767 // t1: first character of string to copy. 5839 // t1: first character of substring to copy.
5768 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); 5840 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
5769 StringHelper::GenerateCopyCharactersLong( 5841 StringHelper::GenerateCopyCharactersLong(
5770 masm, a1, t1, a2, a3, t0, t2, t3, t4, DEST_ALWAYS_ALIGNED); 5842 masm, a1, t1, a2, a3, t0, t2, t3, t4, DEST_ALWAYS_ALIGNED);
5843 __ jmp(&return_v0);
5844
5845 if (FLAG_string_slices) {
5846 __ bind(&create_slice);
5847 // v0: original string
5848 // a1: instance type
5849 // a2: length
5850 // a3: from index (untagged smi)
5851 // t2 (a.k.a. to): to (smi)
5852 // t3 (a.k.a. from): from offset (smi)
5853 Label allocate_slice, sliced_string, seq_string;
5854 STATIC_ASSERT(kSeqStringTag == 0);
5855 __ And(t4, a1, Operand(kStringRepresentationMask));
5856 __ Branch(&seq_string, eq, t4, Operand(zero_reg));
5857 STATIC_ASSERT(kIsIndirectStringMask == (kSlicedStringTag & kConsStringTag));
5858 STATIC_ASSERT(kIsIndirectStringMask != 0);
5859 __ And(t4, a1, Operand(kIsIndirectStringMask));
5860 // External string. Jump to runtime.
5861 __ Branch(&sub_string_runtime, eq, t4, Operand(zero_reg));
5862
5863 __ And(t4, a1, Operand(kSlicedNotConsMask));
5864 __ Branch(&sliced_string, ne, t4, Operand(zero_reg));
5865 // Cons string. Check whether it is flat, then fetch first part.
5866 __ lw(t1, FieldMemOperand(v0, ConsString::kSecondOffset));
5867 __ LoadRoot(t5, Heap::kEmptyStringRootIndex);
5868 __ Branch(&sub_string_runtime, ne, t1, Operand(t5));
5869 __ lw(t1, FieldMemOperand(v0, ConsString::kFirstOffset));
5870 __ jmp(&allocate_slice);
5871
5872 __ bind(&sliced_string);
5873 // Sliced string. Fetch parent and correct start index by offset.
5874 __ lw(t1, FieldMemOperand(v0, SlicedString::kOffsetOffset));
5875 __ addu(t3, t3, t1);
5876 __ lw(t1, FieldMemOperand(v0, SlicedString::kParentOffset));
5877 __ jmp(&allocate_slice);
5878
5879 __ bind(&seq_string);
5880 // Sequential string. Just move string to the right register.
5881 __ mov(t1, v0);
5882
5883 __ bind(&allocate_slice);
5884 // a1: instance type of original string
5885 // a2: length
5886 // t1: underlying subject string
5887 // t3 (a.k.a. from): from offset (smi)
5888 // Allocate new sliced string. At this point we do not reload the instance
5889 // type including the string encoding because we simply rely on the info
5890 // provided by the original string. It does not matter if the original
5891 // string's encoding is wrong because we always have to recheck encoding of
5892 // the newly created string's parent anyways due to externalized strings.
5893 Label two_byte_slice, set_slice_header;
5894 STATIC_ASSERT((kStringEncodingMask & kAsciiStringTag) != 0);
5895 STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
5896 __ And(t4, a1, Operand(kStringEncodingMask));
5897 __ Branch(&two_byte_slice, eq, t4, Operand(zero_reg));
5898 __ AllocateAsciiSlicedString(v0, a2, a3, t0, &sub_string_runtime);
5899 __ jmp(&set_slice_header);
5900 __ bind(&two_byte_slice);
5901 __ AllocateTwoByteSlicedString(v0, a2, a3, t0, &sub_string_runtime);
5902 __ bind(&set_slice_header);
5903 __ sw(t3, FieldMemOperand(v0, SlicedString::kOffsetOffset));
5904 __ sw(t1, FieldMemOperand(v0, SlicedString::kParentOffset));
5905 }
5906
5907 __ bind(&return_v0);
5771 __ IncrementCounter(counters->sub_string_native(), 1, a3, t0); 5908 __ IncrementCounter(counters->sub_string_native(), 1, a3, t0);
5772 __ Addu(sp, sp, Operand(3 * kPointerSize)); 5909 __ Addu(sp, sp, Operand(3 * kPointerSize));
5773 __ Ret(); 5910 __ Ret();
5774 5911
5775 // Just jump to runtime to create the sub string. 5912 // Just jump to runtime to create the sub string.
5776 __ bind(&sub_string_runtime); 5913 __ bind(&sub_string_runtime);
5777 __ TailCallRuntime(Runtime::kSubString, 3, 1); 5914 __ TailCallRuntime(Runtime::kSubString, 3, 1);
5778 } 5915 }
5779 5916
5780 5917
(...skipping 1040 matching lines...) Expand 10 before | Expand all | Expand 10 after
6821 __ mov(result, zero_reg); 6958 __ mov(result, zero_reg);
6822 __ Ret(); 6959 __ Ret();
6823 } 6960 }
6824 6961
6825 6962
6826 #undef __ 6963 #undef __
6827 6964
6828 } } // namespace v8::internal 6965 } } // namespace v8::internal
6829 6966
6830 #endif // V8_TARGET_ARCH_MIPS 6967 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « src/mips/builtins-mips.cc ('k') | src/mips/constants-mips.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698