| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |