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 4499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4510 __ lw(a0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset)); | 4510 __ lw(a0, FieldMemOperand(last_match_info_elements, HeapObject::kMapOffset)); |
4511 __ Branch(&runtime, ne, a0, Operand( | 4511 __ Branch(&runtime, ne, a0, Operand( |
4512 masm->isolate()->factory()->fixed_array_map())); | 4512 masm->isolate()->factory()->fixed_array_map())); |
4513 // Check that the last match info has space for the capture registers and the | 4513 // Check that the last match info has space for the capture registers and the |
4514 // additional information. | 4514 // additional information. |
4515 __ lw(a0, | 4515 __ lw(a0, |
4516 FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset)); | 4516 FieldMemOperand(last_match_info_elements, FixedArray::kLengthOffset)); |
4517 __ Addu(a2, a2, Operand(RegExpImpl::kLastMatchOverhead)); | 4517 __ Addu(a2, a2, Operand(RegExpImpl::kLastMatchOverhead)); |
4518 __ sra(at, a0, kSmiTagSize); // Untag length for comparison. | 4518 __ sra(at, a0, kSmiTagSize); // Untag length for comparison. |
4519 __ Branch(&runtime, gt, a2, Operand(at)); | 4519 __ Branch(&runtime, gt, a2, Operand(at)); |
| 4520 |
| 4521 // Reset offset for possibly sliced string. |
| 4522 __ mov(t0, zero_reg); |
4520 // subject: Subject string | 4523 // subject: Subject string |
4521 // regexp_data: RegExp data (FixedArray) | 4524 // regexp_data: RegExp data (FixedArray) |
4522 // Check the representation and encoding of the subject string. | 4525 // Check the representation and encoding of the subject string. |
4523 Label seq_string; | 4526 Label seq_string; |
4524 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); | 4527 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); |
4525 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); | 4528 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); |
4526 // First check for flat string. | 4529 // First check for flat string. |
4527 __ And(at, a0, Operand(kIsNotStringMask | kStringRepresentationMask)); | 4530 __ And(at, a0, Operand(kIsNotStringMask | kStringRepresentationMask)); |
4528 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); | 4531 STATIC_ASSERT((kStringTag | kSeqStringTag) == 0); |
4529 __ Branch(&seq_string, eq, at, Operand(zero_reg)); | 4532 __ Branch(&seq_string, eq, at, Operand(zero_reg)); |
4530 | 4533 |
4531 // subject: Subject string | 4534 // subject: Subject string |
4532 // a0: instance type if Subject string | 4535 // a0: instance type if Subject string |
4533 // regexp_data: RegExp data (FixedArray) | 4536 // regexp_data: RegExp data (FixedArray) |
4534 // Check for flat cons string. | 4537 // Check for flat cons string or sliced string. |
4535 // A flat cons string is a cons string where the second part is the empty | 4538 // 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 | 4539 // 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 | 4540 // string. Also in this case the first part of the cons string is known to be |
4538 // a sequential string or an external string. | 4541 // a sequential string or an external string. |
4539 STATIC_ASSERT(kExternalStringTag != 0); | 4542 // In the case of a sliced string its offset has to be taken into account. |
4540 STATIC_ASSERT((kConsStringTag & kExternalStringTag) == 0); | 4543 Label cons_string, check_encoding; |
4541 __ And(at, a0, Operand(kIsNotStringMask | kExternalStringTag)); | 4544 STATIC_ASSERT((kConsStringTag < kExternalStringTag)); |
4542 __ Branch(&runtime, ne, at, Operand(zero_reg)); | 4545 STATIC_ASSERT((kSlicedStringTag > kExternalStringTag)); |
| 4546 __ Branch(&cons_string, lt, at, Operand(kExternalStringTag)); |
| 4547 __ Branch(&runtime, eq, at, Operand(kExternalStringTag)); |
| 4548 |
| 4549 // String is sliced. |
| 4550 __ lw(t0, FieldMemOperand(subject, SlicedString::kOffsetOffset)); |
| 4551 __ sra(t0, t0, kSmiTagSize); |
| 4552 __ lw(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); |
| 4553 // t5: offset of sliced string, smi-tagged. |
| 4554 __ jmp(&check_encoding); |
| 4555 // String is a cons string, check whether it is flat. |
| 4556 __ bind(&cons_string); |
4543 __ lw(a0, FieldMemOperand(subject, ConsString::kSecondOffset)); | 4557 __ lw(a0, FieldMemOperand(subject, ConsString::kSecondOffset)); |
4544 __ LoadRoot(a1, Heap::kEmptyStringRootIndex); | 4558 __ LoadRoot(a1, Heap::kEmptyStringRootIndex); |
4545 __ Branch(&runtime, ne, a0, Operand(a1)); | 4559 __ Branch(&runtime, ne, a0, Operand(a1)); |
4546 __ lw(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); | 4560 __ lw(subject, FieldMemOperand(subject, ConsString::kFirstOffset)); |
| 4561 // Is first part of cons or parent of slice a flat string? |
| 4562 __ bind(&check_encoding); |
4547 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); | 4563 __ lw(a0, FieldMemOperand(subject, HeapObject::kMapOffset)); |
4548 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); | 4564 __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); |
4549 // Is first part a flat string? | |
4550 STATIC_ASSERT(kSeqStringTag == 0); | 4565 STATIC_ASSERT(kSeqStringTag == 0); |
4551 __ And(at, a0, Operand(kStringRepresentationMask)); | 4566 __ And(at, a0, Operand(kStringRepresentationMask)); |
4552 __ Branch(&runtime, ne, at, Operand(zero_reg)); | 4567 __ Branch(&runtime, ne, at, Operand(zero_reg)); |
4553 | 4568 |
4554 __ bind(&seq_string); | 4569 __ bind(&seq_string); |
4555 // subject: Subject string | 4570 // subject: Subject string |
4556 // regexp_data: RegExp data (FixedArray) | 4571 // regexp_data: RegExp data (FixedArray) |
4557 // a0: Instance type of subject string | 4572 // a0: Instance type of subject string |
4558 STATIC_ASSERT(kStringEncodingMask == 4); | 4573 STATIC_ASSERT(kStringEncodingMask == 4); |
4559 STATIC_ASSERT(kAsciiStringTag == 4); | 4574 STATIC_ASSERT(kAsciiStringTag == 4); |
4560 STATIC_ASSERT(kTwoByteStringTag == 0); | 4575 STATIC_ASSERT(kTwoByteStringTag == 0); |
4561 // Find the code object based on the assumptions above. | 4576 // Find the code object based on the assumptions above. |
4562 __ And(a0, a0, Operand(kStringEncodingMask)); // Non-zero for ascii. | 4577 __ And(a0, a0, Operand(kStringEncodingMask)); // Non-zero for ascii. |
4563 __ lw(t9, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset)); | 4578 __ lw(t9, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset)); |
4564 __ sra(a3, a0, 2); // a3 is 1 for ascii, 0 for UC16 (usyed below). | 4579 __ sra(a3, a0, 2); // a3 is 1 for ascii, 0 for UC16 (usyed below). |
4565 __ lw(t0, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset)); | 4580 __ lw(t1, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset)); |
4566 __ movz(t9, t0, a0); // If UC16 (a0 is 0), replace t9 w/kDataUC16CodeOffset. | 4581 __ movz(t9, t1, a0); // If UC16 (a0 is 0), replace t9 w/kDataUC16CodeOffset. |
4567 | 4582 |
4568 // Check that the irregexp code has been generated for the actual string | 4583 // 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 | 4584 // encoding. If it has, the field contains a code object otherwise it contains |
4570 // a smi (code flushing support). | 4585 // a smi (code flushing support). |
4571 __ JumpIfSmi(t9, &runtime); | 4586 __ JumpIfSmi(t9, &runtime); |
4572 | 4587 |
4573 // a3: encoding of subject string (1 if ASCII, 0 if two_byte); | 4588 // a3: encoding of subject string (1 if ASCII, 0 if two_byte); |
4574 // t9: code | 4589 // t9: code |
4575 // subject: Subject string | 4590 // subject: Subject string |
4576 // regexp_data: RegExp data (FixedArray) | 4591 // regexp_data: RegExp data (FixedArray) |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4623 __ addu(a0, a0, a2); | 4638 __ addu(a0, a0, a2); |
4624 __ sw(a0, MemOperand(sp, 2 * kPointerSize)); | 4639 __ sw(a0, MemOperand(sp, 2 * kPointerSize)); |
4625 | 4640 |
4626 // Argument 5: static offsets vector buffer. | 4641 // Argument 5: static offsets vector buffer. |
4627 __ li(a0, Operand( | 4642 __ li(a0, Operand( |
4628 ExternalReference::address_of_static_offsets_vector(masm->isolate()))); | 4643 ExternalReference::address_of_static_offsets_vector(masm->isolate()))); |
4629 __ sw(a0, MemOperand(sp, 1 * kPointerSize)); | 4644 __ sw(a0, MemOperand(sp, 1 * kPointerSize)); |
4630 | 4645 |
4631 // For arguments 4 and 3 get string length, calculate start of string data | 4646 // 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). | 4647 // 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); | 4648 STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize); |
4636 __ Addu(t0, subject, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 4649 __ Addu(t2, subject, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
4637 __ Xor(a3, a3, Operand(1)); // 1 for 2-byte str, 0 for 1-byte. | 4650 __ Xor(a3, a3, Operand(1)); // 1 for 2-byte str, 0 for 1-byte. |
4638 // Argument 4 (a3): End of string data | 4651 // Load the length from the original subject string from the previous stack |
4639 // Argument 3 (a2): Start of string data | 4652 // frame. Therefore we have to use fp, which points exactly to two pointer |
| 4653 // sizes below the previous sp. (Because creating a new stack frame pushes |
| 4654 // the previous fp onto the stack and moves up sp by 2 * kPointerSize.) |
| 4655 __ lw(a0, MemOperand(fp, kSubjectOffset + 2 * kPointerSize)); |
| 4656 // If slice offset is not 0, load the length from the original sliced string. |
| 4657 // Argument 4, a3: End of string data |
| 4658 // Argument 3, a2: Start of string data |
| 4659 // Prepare start and end index of the input. |
| 4660 __ sllv(t1, t0, a3); |
| 4661 __ addu(t0, t2, t1); |
4640 __ sllv(t1, a1, a3); | 4662 __ sllv(t1, a1, a3); |
4641 __ addu(a2, t0, t1); | 4663 __ addu(a2, t0, t1); |
4642 __ sllv(t1, a0, a3); | 4664 |
| 4665 __ lw(t2, FieldMemOperand(a0, String::kLengthOffset)); |
| 4666 __ sra(t2, t2, kSmiTagSize); |
| 4667 __ sllv(t1, t2, a3); |
4643 __ addu(a3, t0, t1); | 4668 __ addu(a3, t0, t1); |
4644 | |
4645 // Argument 2 (a1): Previous index. | 4669 // Argument 2 (a1): Previous index. |
4646 // Already there | 4670 // Already there |
4647 | 4671 |
4648 // Argument 1 (a0): Subject string. | 4672 // Argument 1 (a0): Subject string. |
4649 __ mov(a0, subject); | 4673 // Already there |
4650 | 4674 |
4651 // Locate the code entry and call it. | 4675 // Locate the code entry and call it. |
4652 __ Addu(t9, t9, Operand(Code::kHeaderSize - kHeapObjectTag)); | 4676 __ Addu(t9, t9, Operand(Code::kHeaderSize - kHeapObjectTag)); |
4653 DirectCEntryStub stub; | 4677 DirectCEntryStub stub; |
4654 stub.GenerateCall(masm, t9); | 4678 stub.GenerateCall(masm, t9); |
4655 | 4679 |
4656 __ LeaveExitFrame(false, no_reg); | 4680 __ LeaveExitFrame(false, no_reg); |
4657 | 4681 |
4658 // v0: result | 4682 // v0: result |
4659 // subject: subject string (callee saved) | 4683 // subject: subject string (callee saved) |
4660 // regexp_data: RegExp data (callee saved) | 4684 // regexp_data: RegExp data (callee saved) |
4661 // last_match_info_elements: Last match info elements (callee saved) | 4685 // last_match_info_elements: Last match info elements (callee saved) |
4662 | 4686 |
4663 // Check the result. | 4687 // Check the result. |
4664 | 4688 |
4665 Label success; | 4689 Label success; |
4666 __ Branch(&success, eq, v0, Operand(NativeRegExpMacroAssembler::SUCCESS)); | 4690 __ Branch(&success, eq, |
| 4691 subject, Operand(NativeRegExpMacroAssembler::SUCCESS)); |
4667 Label failure; | 4692 Label failure; |
4668 __ Branch(&failure, eq, v0, Operand(NativeRegExpMacroAssembler::FAILURE)); | 4693 __ Branch(&failure, eq, |
| 4694 subject, Operand(NativeRegExpMacroAssembler::FAILURE)); |
4669 // If not exception it can only be retry. Handle that in the runtime system. | 4695 // If not exception it can only be retry. Handle that in the runtime system. |
4670 __ Branch(&runtime, ne, v0, Operand(NativeRegExpMacroAssembler::EXCEPTION)); | 4696 __ Branch(&runtime, ne, |
| 4697 subject, Operand(NativeRegExpMacroAssembler::EXCEPTION)); |
4671 // Result must now be exception. If there is no pending exception already a | 4698 // 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 | 4699 // 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. | 4700 // haven't created the exception yet. Handle that in the runtime system. |
4674 // TODO(592): Rerunning the RegExp to get the stack overflow exception. | 4701 // TODO(592): Rerunning the RegExp to get the stack overflow exception. |
4675 __ li(a1, Operand( | 4702 __ li(a1, Operand( |
4676 ExternalReference::the_hole_value_location(masm->isolate()))); | 4703 ExternalReference::the_hole_value_location(masm->isolate()))); |
4677 __ lw(a1, MemOperand(a1, 0)); | 4704 __ lw(a1, MemOperand(a1, 0)); |
4678 __ li(a2, Operand(ExternalReference(Isolate::k_pending_exception_address, | 4705 __ li(a2, Operand(ExternalReference(Isolate::k_pending_exception_address, |
4679 masm->isolate()))); | 4706 masm->isolate()))); |
4680 __ lw(v0, MemOperand(a2, 0)); | 4707 __ lw(v0, MemOperand(a2, 0)); |
4681 __ Branch(&runtime, eq, v0, Operand(a1)); | 4708 __ Branch(&runtime, eq, subject, Operand(a1)); |
4682 | 4709 |
4683 __ sw(a1, MemOperand(a2, 0)); // Clear pending exception. | 4710 __ sw(a1, MemOperand(a2, 0)); // Clear pending exception. |
4684 | 4711 |
4685 // Check if the exception is a termination. If so, throw as uncatchable. | 4712 // Check if the exception is a termination. If so, throw as uncatchable. |
4686 __ LoadRoot(a0, Heap::kTerminationExceptionRootIndex); | 4713 __ LoadRoot(a0, Heap::kTerminationExceptionRootIndex); |
4687 Label termination_exception; | 4714 Label termination_exception; |
4688 __ Branch(&termination_exception, eq, v0, Operand(a0)); | 4715 __ Branch(&termination_exception, eq, subject, Operand(a0)); |
4689 | 4716 |
4690 __ Throw(a0); // Expects thrown value in v0. | 4717 __ Throw(subject); // Expects thrown value in v0. |
4691 | 4718 |
4692 __ bind(&termination_exception); | 4719 __ bind(&termination_exception); |
4693 __ ThrowUncatchable(TERMINATION, v0); // Expects thrown value in v0. | 4720 __ ThrowUncatchable(TERMINATION, v0); // Expects thrown value in v0. |
4694 | 4721 |
4695 __ bind(&failure); | 4722 __ bind(&failure); |
4696 // For failure and exception return null. | 4723 // For failure and exception return null. |
4697 __ li(v0, Operand(masm->isolate()->factory()->null_value())); | 4724 __ li(v0, Operand(masm->isolate()->factory()->null_value())); |
4698 __ Addu(sp, sp, Operand(4 * kPointerSize)); | 4725 __ Addu(sp, sp, Operand(4 * kPointerSize)); |
4699 __ Ret(); | 4726 __ Ret(); |
4700 | 4727 |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4956 | NeverNanNanField::encode(cc_ == eq ? never_nan_nan_ : false) | 4983 | NeverNanNanField::encode(cc_ == eq ? never_nan_nan_ : false) |
4957 | IncludeSmiCompareField::encode(include_smi_compare_); | 4984 | IncludeSmiCompareField::encode(include_smi_compare_); |
4958 } | 4985 } |
4959 | 4986 |
4960 | 4987 |
4961 // StringCharCodeAtGenerator. | 4988 // StringCharCodeAtGenerator. |
4962 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { | 4989 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { |
4963 Label flat_string; | 4990 Label flat_string; |
4964 Label ascii_string; | 4991 Label ascii_string; |
4965 Label got_char_code; | 4992 Label got_char_code; |
| 4993 Label sliced_string; |
4966 | 4994 |
4967 ASSERT(!t0.is(scratch_)); | 4995 ASSERT(!t0.is(scratch_)); |
4968 ASSERT(!t0.is(index_)); | 4996 ASSERT(!t0.is(index_)); |
4969 ASSERT(!t0.is(result_)); | 4997 ASSERT(!t0.is(result_)); |
4970 ASSERT(!t0.is(object_)); | 4998 ASSERT(!t0.is(object_)); |
4971 | 4999 |
4972 // If the receiver is a smi trigger the non-string case. | 5000 // If the receiver is a smi trigger the non-string case. |
4973 __ JumpIfSmi(object_, receiver_not_string_); | 5001 __ JumpIfSmi(object_, receiver_not_string_); |
4974 | 5002 |
4975 // Fetch the instance type of the receiver into result register. | 5003 // Fetch the instance type of the receiver into result register. |
(...skipping 13 matching lines...) Expand all Loading... |
4989 // Check for index out of range. | 5017 // Check for index out of range. |
4990 __ lw(t0, FieldMemOperand(object_, String::kLengthOffset)); | 5018 __ lw(t0, FieldMemOperand(object_, String::kLengthOffset)); |
4991 __ Branch(index_out_of_range_, ls, t0, Operand(scratch_)); | 5019 __ Branch(index_out_of_range_, ls, t0, Operand(scratch_)); |
4992 | 5020 |
4993 // We need special handling for non-flat strings. | 5021 // We need special handling for non-flat strings. |
4994 STATIC_ASSERT(kSeqStringTag == 0); | 5022 STATIC_ASSERT(kSeqStringTag == 0); |
4995 __ And(t0, result_, Operand(kStringRepresentationMask)); | 5023 __ And(t0, result_, Operand(kStringRepresentationMask)); |
4996 __ Branch(&flat_string, eq, t0, Operand(zero_reg)); | 5024 __ Branch(&flat_string, eq, t0, Operand(zero_reg)); |
4997 | 5025 |
4998 // Handle non-flat strings. | 5026 // Handle non-flat strings. |
4999 __ And(t0, result_, Operand(kIsConsStringMask)); | 5027 __ And(result_, result_, Operand(kStringRepresentationMask)); |
5000 __ Branch(&call_runtime_, eq, t0, Operand(zero_reg)); | 5028 STATIC_ASSERT((kConsStringTag < kExternalStringTag)); |
| 5029 STATIC_ASSERT((kSlicedStringTag > kExternalStringTag)); |
| 5030 __ Branch(&sliced_string, gt, result_, Operand(kExternalStringTag)); |
| 5031 __ Branch(&call_runtime_, eq, result_, Operand(kExternalStringTag)); |
5001 | 5032 |
5002 // ConsString. | 5033 // ConsString. |
5003 // Check whether the right hand side is the empty string (i.e. if | 5034 // 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 | 5035 // 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 | 5036 // the case we would rather go to the runtime system now to flatten |
5006 // the string. | 5037 // the string. |
| 5038 Label assure_seq_string; |
5007 __ lw(result_, FieldMemOperand(object_, ConsString::kSecondOffset)); | 5039 __ lw(result_, FieldMemOperand(object_, ConsString::kSecondOffset)); |
5008 __ LoadRoot(t0, Heap::kEmptyStringRootIndex); | 5040 __ LoadRoot(t0, Heap::kEmptyStringRootIndex); |
5009 __ Branch(&call_runtime_, ne, result_, Operand(t0)); | 5041 __ Branch(&call_runtime_, ne, result_, Operand(t0)); |
5010 | 5042 |
5011 // Get the first of the two strings and load its instance type. | 5043 // Get the first of the two strings and load its instance type. |
5012 __ lw(object_, FieldMemOperand(object_, ConsString::kFirstOffset)); | 5044 __ lw(object_, FieldMemOperand(object_, ConsString::kFirstOffset)); |
| 5045 __ jmp(&assure_seq_string); |
| 5046 |
| 5047 // SlicedString, unpack and add offset. |
| 5048 __ bind(&sliced_string); |
| 5049 __ lw(result_, FieldMemOperand(object_, SlicedString::kOffsetOffset)); |
| 5050 __ addu(scratch_, scratch_, result_); |
| 5051 __ lw(object_, FieldMemOperand(object_, SlicedString::kParentOffset)); |
| 5052 |
| 5053 // Assure that we are dealing with a sequential string. Go to runtime if not. |
| 5054 __ bind(&assure_seq_string); |
5013 __ lw(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); | 5055 __ lw(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); |
5014 __ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); | 5056 __ lbu(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); |
5015 // If the first cons component is also non-flat, then go to runtime. | 5057 // Check that parent is not an external string. Go to runtime otherwise. |
5016 STATIC_ASSERT(kSeqStringTag == 0); | 5058 STATIC_ASSERT(kSeqStringTag == 0); |
5017 | 5059 |
5018 __ And(t0, result_, Operand(kStringRepresentationMask)); | 5060 __ And(t0, result_, Operand(kStringRepresentationMask)); |
5019 __ Branch(&call_runtime_, ne, t0, Operand(zero_reg)); | 5061 __ Branch(&call_runtime_, ne, t0, Operand(zero_reg)); |
5020 | 5062 |
5021 // Check for 1-byte or 2-byte string. | 5063 // Check for 1-byte or 2-byte string. |
5022 __ bind(&flat_string); | 5064 __ bind(&flat_string); |
5023 STATIC_ASSERT(kAsciiStringTag != 0); | 5065 STATIC_ASSERT(kAsciiStringTag != 0); |
5024 __ And(t0, result_, Operand(kStringEncodingMask)); | 5066 __ And(t0, result_, Operand(kStringEncodingMask)); |
5025 __ Branch(&ascii_string, ne, t0, Operand(zero_reg)); | 5067 __ Branch(&ascii_string, ne, t0, Operand(zero_reg)); |
(...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5576 // 0 <= from <= to <= string.length. | 5618 // 0 <= from <= to <= string.length. |
5577 // If any of these assumptions fail, we call the runtime system. | 5619 // If any of these assumptions fail, we call the runtime system. |
5578 | 5620 |
5579 static const int kToOffset = 0 * kPointerSize; | 5621 static const int kToOffset = 0 * kPointerSize; |
5580 static const int kFromOffset = 1 * kPointerSize; | 5622 static const int kFromOffset = 1 * kPointerSize; |
5581 static const int kStringOffset = 2 * kPointerSize; | 5623 static const int kStringOffset = 2 * kPointerSize; |
5582 | 5624 |
5583 Register to = t2; | 5625 Register to = t2; |
5584 Register from = t3; | 5626 Register from = t3; |
5585 | 5627 |
| 5628 if (FLAG_string_slices) { |
| 5629 __ nop(); // Jumping as first instruction would crash the code generation. |
| 5630 __ jmp(&sub_string_runtime); |
| 5631 } |
| 5632 |
5586 // Check bounds and smi-ness. | 5633 // Check bounds and smi-ness. |
5587 __ lw(to, MemOperand(sp, kToOffset)); | 5634 __ lw(to, MemOperand(sp, kToOffset)); |
5588 __ lw(from, MemOperand(sp, kFromOffset)); | 5635 __ lw(from, MemOperand(sp, kFromOffset)); |
5589 STATIC_ASSERT(kFromOffset == kToOffset + 4); | 5636 STATIC_ASSERT(kFromOffset == kToOffset + 4); |
5590 STATIC_ASSERT(kSmiTag == 0); | 5637 STATIC_ASSERT(kSmiTag == 0); |
5591 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); | 5638 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); |
5592 | 5639 |
5593 __ JumpIfNotSmi(from, &sub_string_runtime); | 5640 __ JumpIfNotSmi(from, &sub_string_runtime); |
5594 __ JumpIfNotSmi(to, &sub_string_runtime); | 5641 __ JumpIfNotSmi(to, &sub_string_runtime); |
5595 | 5642 |
(...skipping 1225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6821 __ mov(result, zero_reg); | 6868 __ mov(result, zero_reg); |
6822 __ Ret(); | 6869 __ Ret(); |
6823 } | 6870 } |
6824 | 6871 |
6825 | 6872 |
6826 #undef __ | 6873 #undef __ |
6827 | 6874 |
6828 } } // namespace v8::internal | 6875 } } // namespace v8::internal |
6829 | 6876 |
6830 #endif // V8_TARGET_ARCH_MIPS | 6877 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |