OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 8480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8491 // Check that the second argument is a string. | 8491 // Check that the second argument is a string. |
8492 __ ldr(subject, MemOperand(sp, kSubjectOffset)); | 8492 __ ldr(subject, MemOperand(sp, kSubjectOffset)); |
8493 __ tst(subject, Operand(kSmiTagMask)); | 8493 __ tst(subject, Operand(kSmiTagMask)); |
8494 __ b(eq, &runtime); | 8494 __ b(eq, &runtime); |
8495 Condition is_string = masm->IsObjectStringType(subject, r0); | 8495 Condition is_string = masm->IsObjectStringType(subject, r0); |
8496 __ b(NegateCondition(is_string), &runtime); | 8496 __ b(NegateCondition(is_string), &runtime); |
8497 // Get the length of the string to r3. | 8497 // Get the length of the string to r3. |
8498 __ ldr(r3, FieldMemOperand(subject, String::kLengthOffset)); | 8498 __ ldr(r3, FieldMemOperand(subject, String::kLengthOffset)); |
8499 | 8499 |
8500 // r2: Number of capture registers | 8500 // r2: Number of capture registers |
8501 // r3: Length of subject string | 8501 // r3: Length of subject string as a smi |
8502 // subject: Subject string | 8502 // subject: Subject string |
8503 // regexp_data: RegExp data (FixedArray) | 8503 // regexp_data: RegExp data (FixedArray) |
8504 // Check that the third argument is a positive smi less than the subject | 8504 // Check that the third argument is a positive smi less than the subject |
8505 // string length. A negative value will be greater (unsigned comparison). | 8505 // string length. A negative value will be greater (unsigned comparison). |
8506 __ ldr(r0, MemOperand(sp, kPreviousIndexOffset)); | 8506 __ ldr(r0, MemOperand(sp, kPreviousIndexOffset)); |
8507 __ cmp(r3, Operand(r0, ASR, kSmiTagSize + kSmiShiftSize)); | 8507 __ tst(r0, Operand(kSmiTagMask)); |
8508 __ b(ls, &runtime); | 8508 __ b(eq, &runtime); |
| 8509 __ cmp(r3, Operand(r0)); |
| 8510 __ b(le, &runtime); |
8509 | 8511 |
8510 // r2: Number of capture registers | 8512 // r2: Number of capture registers |
8511 // subject: Subject string | 8513 // subject: Subject string |
8512 // regexp_data: RegExp data (FixedArray) | 8514 // regexp_data: RegExp data (FixedArray) |
8513 // Check that the fourth object is a JSArray object. | 8515 // Check that the fourth object is a JSArray object. |
8514 __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset)); | 8516 __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset)); |
8515 __ tst(r0, Operand(kSmiTagMask)); | 8517 __ tst(r0, Operand(kSmiTagMask)); |
8516 __ b(eq, &runtime); | 8518 __ b(eq, &runtime); |
8517 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); | 8519 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); |
8518 __ b(ne, &runtime); | 8520 __ b(ne, &runtime); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8624 __ add(r0, r0, Operand(r2)); | 8626 __ add(r0, r0, Operand(r2)); |
8625 __ str(r0, MemOperand(sp, 1 * kPointerSize)); | 8627 __ str(r0, MemOperand(sp, 1 * kPointerSize)); |
8626 | 8628 |
8627 // Argument 5 (sp[0]): static offsets vector buffer. | 8629 // Argument 5 (sp[0]): static offsets vector buffer. |
8628 __ mov(r0, Operand(ExternalReference::address_of_static_offsets_vector())); | 8630 __ mov(r0, Operand(ExternalReference::address_of_static_offsets_vector())); |
8629 __ str(r0, MemOperand(sp, 0 * kPointerSize)); | 8631 __ str(r0, MemOperand(sp, 0 * kPointerSize)); |
8630 | 8632 |
8631 // For arguments 4 and 3 get string length, calculate start of string data and | 8633 // For arguments 4 and 3 get string length, calculate start of string data and |
8632 // calculate the shift of the index (0 for ASCII and 1 for two byte). | 8634 // calculate the shift of the index (0 for ASCII and 1 for two byte). |
8633 __ ldr(r0, FieldMemOperand(subject, String::kLengthOffset)); | 8635 __ ldr(r0, FieldMemOperand(subject, String::kLengthOffset)); |
| 8636 __ mov(r0, Operand(r0, ASR, kSmiTagSize)); |
8634 ASSERT_EQ(SeqAsciiString::kHeaderSize, SeqTwoByteString::kHeaderSize); | 8637 ASSERT_EQ(SeqAsciiString::kHeaderSize, SeqTwoByteString::kHeaderSize); |
8635 __ add(r9, subject, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 8638 __ add(r9, subject, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
8636 __ eor(r3, r3, Operand(1)); | 8639 __ eor(r3, r3, Operand(1)); |
8637 // Argument 4 (r3): End of string data | 8640 // Argument 4 (r3): End of string data |
8638 // Argument 3 (r2): Start of string data | 8641 // Argument 3 (r2): Start of string data |
8639 __ add(r2, r9, Operand(r1, LSL, r3)); | 8642 __ add(r2, r9, Operand(r1, LSL, r3)); |
8640 __ add(r3, r9, Operand(r0, LSL, r3)); | 8643 __ add(r3, r9, Operand(r0, LSL, r3)); |
8641 | 8644 |
8642 // Argument 2 (r1): Previous index. | 8645 // Argument 2 (r1): Previous index. |
8643 // Already there | 8646 // Already there |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8883 // If the receiver is not a string trigger the non-string case. | 8886 // If the receiver is not a string trigger the non-string case. |
8884 __ tst(result, Operand(kIsNotStringMask)); | 8887 __ tst(result, Operand(kIsNotStringMask)); |
8885 __ b(ne, receiver_not_string); | 8888 __ b(ne, receiver_not_string); |
8886 | 8889 |
8887 // If the index is non-smi trigger the non-smi case. | 8890 // If the index is non-smi trigger the non-smi case. |
8888 __ BranchOnNotSmi(index, index_not_smi); | 8891 __ BranchOnNotSmi(index, index_not_smi); |
8889 | 8892 |
8890 // Check for index out of range. | 8893 // Check for index out of range. |
8891 __ ldr(scratch, FieldMemOperand(object, String::kLengthOffset)); | 8894 __ ldr(scratch, FieldMemOperand(object, String::kLengthOffset)); |
8892 // Now scratch has the length of the string. Compare with the index. | 8895 // Now scratch has the length of the string. Compare with the index. |
8893 __ cmp(scratch, Operand(index, LSR, kSmiTagSize)); | 8896 __ cmp(scratch, Operand(index)); |
8894 __ b(ls, index_out_of_range); | 8897 __ b(ls, index_out_of_range); |
8895 | 8898 |
8896 __ bind(&try_again_with_new_string); | 8899 __ bind(&try_again_with_new_string); |
8897 // ----------- S t a t e ------------- | 8900 // ----------- S t a t e ------------- |
8898 // -- object : string to access | 8901 // -- object : string to access |
8899 // -- result : instance type of the string | 8902 // -- result : instance type of the string |
8900 // -- scratch : non-negative index < length | 8903 // -- scratch : non-negative index < length |
8901 // ----------------------------------- | 8904 // ----------------------------------- |
8902 | 8905 |
8903 // We need special handling for non-flat strings. | 8906 // We need special handling for non-flat strings. |
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9270 candidate, | 9273 candidate, |
9271 LSL, | 9274 LSL, |
9272 kPointerSizeLog2)); | 9275 kPointerSizeLog2)); |
9273 | 9276 |
9274 // If entry is undefined no string with this hash can be found. | 9277 // If entry is undefined no string with this hash can be found. |
9275 __ cmp(candidate, undefined); | 9278 __ cmp(candidate, undefined); |
9276 __ b(eq, not_found); | 9279 __ b(eq, not_found); |
9277 | 9280 |
9278 // If length is not 2 the string is not a candidate. | 9281 // If length is not 2 the string is not a candidate. |
9279 __ ldr(scratch, FieldMemOperand(candidate, String::kLengthOffset)); | 9282 __ ldr(scratch, FieldMemOperand(candidate, String::kLengthOffset)); |
9280 __ cmp(scratch, Operand(2)); | 9283 __ cmp(scratch, Operand(Smi::FromInt(2))); |
9281 __ b(ne, &next_probe[i]); | 9284 __ b(ne, &next_probe[i]); |
9282 | 9285 |
9283 // Check that the candidate is a non-external ascii string. | 9286 // Check that the candidate is a non-external ascii string. |
9284 __ ldr(scratch, FieldMemOperand(candidate, HeapObject::kMapOffset)); | 9287 __ ldr(scratch, FieldMemOperand(candidate, HeapObject::kMapOffset)); |
9285 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | 9288 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
9286 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, | 9289 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, |
9287 &next_probe[i]); | 9290 &next_probe[i]); |
9288 | 9291 |
9289 // Check if the two characters match. | 9292 // Check if the two characters match. |
9290 // Assumes that word load is little endian. | 9293 // Assumes that word load is little endian. |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9421 // Definitly a sequential string. | 9424 // Definitly a sequential string. |
9422 __ bind(&seq_string); | 9425 __ bind(&seq_string); |
9423 | 9426 |
9424 // r1: instance type. | 9427 // r1: instance type. |
9425 // r2: length | 9428 // r2: length |
9426 // r3: from index (untaged smi) | 9429 // r3: from index (untaged smi) |
9427 // r5: string | 9430 // r5: string |
9428 // r6: from (smi) | 9431 // r6: from (smi) |
9429 // r7: to (smi) | 9432 // r7: to (smi) |
9430 __ ldr(r4, FieldMemOperand(r5, String::kLengthOffset)); | 9433 __ ldr(r4, FieldMemOperand(r5, String::kLengthOffset)); |
9431 __ cmp(r4, Operand(r7, ASR, 1)); | 9434 __ cmp(r4, Operand(r7)); |
9432 __ b(lt, &runtime); // Fail if to > length. | 9435 __ b(lt, &runtime); // Fail if to > length. |
9433 | 9436 |
9434 // r1: instance type. | 9437 // r1: instance type. |
9435 // r2: result string length. | 9438 // r2: result string length. |
9436 // r3: from index (untaged smi) | 9439 // r3: from index (untaged smi) |
9437 // r5: string. | 9440 // r5: string. |
9438 // r6: from offset (smi) | 9441 // r6: from offset (smi) |
9439 // Check for flat ascii string. | 9442 // Check for flat ascii string. |
9440 Label non_ascii_flat; | 9443 Label non_ascii_flat; |
9441 __ tst(r1, Operand(kStringEncodingMask)); | 9444 __ tst(r1, Operand(kStringEncodingMask)); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9540 Register scratch3, | 9543 Register scratch3, |
9541 Register scratch4) { | 9544 Register scratch4) { |
9542 Label compare_lengths; | 9545 Label compare_lengths; |
9543 // Find minimum length and length difference. | 9546 // Find minimum length and length difference. |
9544 __ ldr(scratch1, FieldMemOperand(left, String::kLengthOffset)); | 9547 __ ldr(scratch1, FieldMemOperand(left, String::kLengthOffset)); |
9545 __ ldr(scratch2, FieldMemOperand(right, String::kLengthOffset)); | 9548 __ ldr(scratch2, FieldMemOperand(right, String::kLengthOffset)); |
9546 __ sub(scratch3, scratch1, Operand(scratch2), SetCC); | 9549 __ sub(scratch3, scratch1, Operand(scratch2), SetCC); |
9547 Register length_delta = scratch3; | 9550 Register length_delta = scratch3; |
9548 __ mov(scratch1, scratch2, LeaveCC, gt); | 9551 __ mov(scratch1, scratch2, LeaveCC, gt); |
9549 Register min_length = scratch1; | 9552 Register min_length = scratch1; |
| 9553 ASSERT(kSmiTag == 0); |
9550 __ tst(min_length, Operand(min_length)); | 9554 __ tst(min_length, Operand(min_length)); |
9551 __ b(eq, &compare_lengths); | 9555 __ b(eq, &compare_lengths); |
9552 | 9556 |
| 9557 // Untag smi. |
| 9558 __ mov(min_length, Operand(min_length, ASR, kSmiTagSize)); |
| 9559 |
9553 // Setup registers so that we only need to increment one register | 9560 // Setup registers so that we only need to increment one register |
9554 // in the loop. | 9561 // in the loop. |
9555 __ add(scratch2, min_length, | 9562 __ add(scratch2, min_length, |
9556 Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 9563 Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
9557 __ add(left, left, Operand(scratch2)); | 9564 __ add(left, left, Operand(scratch2)); |
9558 __ add(right, right, Operand(scratch2)); | 9565 __ add(right, right, Operand(scratch2)); |
9559 // Registers left and right points to the min_length character of strings. | 9566 // Registers left and right points to the min_length character of strings. |
9560 __ rsb(min_length, min_length, Operand(-1)); | 9567 __ rsb(min_length, min_length, Operand(-1)); |
9561 Register index = min_length; | 9568 Register index = min_length; |
9562 // Index starts at -min_length. | 9569 // Index starts at -min_length. |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9652 // Both arguments are strings. | 9659 // Both arguments are strings. |
9653 // r0: first string | 9660 // r0: first string |
9654 // r1: second string | 9661 // r1: second string |
9655 // r4: first string instance type (if string_check_) | 9662 // r4: first string instance type (if string_check_) |
9656 // r5: second string instance type (if string_check_) | 9663 // r5: second string instance type (if string_check_) |
9657 { | 9664 { |
9658 Label strings_not_empty; | 9665 Label strings_not_empty; |
9659 // Check if either of the strings are empty. In that case return the other. | 9666 // Check if either of the strings are empty. In that case return the other. |
9660 __ ldr(r2, FieldMemOperand(r0, String::kLengthOffset)); | 9667 __ ldr(r2, FieldMemOperand(r0, String::kLengthOffset)); |
9661 __ ldr(r3, FieldMemOperand(r1, String::kLengthOffset)); | 9668 __ ldr(r3, FieldMemOperand(r1, String::kLengthOffset)); |
9662 __ cmp(r2, Operand(0)); // Test if first string is empty. | 9669 ASSERT(kSmiTag == 0); |
| 9670 __ cmp(r2, Operand(Smi::FromInt(0))); // Test if first string is empty. |
9663 __ mov(r0, Operand(r1), LeaveCC, eq); // If first is empty, return second. | 9671 __ mov(r0, Operand(r1), LeaveCC, eq); // If first is empty, return second. |
9664 __ cmp(r3, Operand(0), ne); // Else test if second string is empty. | 9672 ASSERT(kSmiTag == 0); |
| 9673 // Else test if second string is empty. |
| 9674 __ cmp(r3, Operand(Smi::FromInt(0)), ne); |
9665 __ b(ne, &strings_not_empty); // If either string was empty, return r0. | 9675 __ b(ne, &strings_not_empty); // If either string was empty, return r0. |
9666 | 9676 |
9667 __ IncrementCounter(&Counters::string_add_native, 1, r2, r3); | 9677 __ IncrementCounter(&Counters::string_add_native, 1, r2, r3); |
9668 __ add(sp, sp, Operand(2 * kPointerSize)); | 9678 __ add(sp, sp, Operand(2 * kPointerSize)); |
9669 __ Ret(); | 9679 __ Ret(); |
9670 | 9680 |
9671 __ bind(&strings_not_empty); | 9681 __ bind(&strings_not_empty); |
9672 } | 9682 } |
9673 | 9683 |
| 9684 __ mov(r2, Operand(r2, ASR, kSmiTagSize)); |
| 9685 __ mov(r3, Operand(r3, ASR, kSmiTagSize)); |
9674 // Both strings are non-empty. | 9686 // Both strings are non-empty. |
9675 // r0: first string | 9687 // r0: first string |
9676 // r1: second string | 9688 // r1: second string |
9677 // r2: length of first string | 9689 // r2: length of first string |
9678 // r3: length of second string | 9690 // r3: length of second string |
9679 // r4: first string instance type (if string_check_) | 9691 // r4: first string instance type (if string_check_) |
9680 // r5: second string instance type (if string_check_) | 9692 // r5: second string instance type (if string_check_) |
9681 // Look at the length of the result of adding the two strings. | 9693 // Look at the length of the result of adding the two strings. |
9682 Label string_add_flat_result, longer_than_two; | 9694 Label string_add_flat_result, longer_than_two; |
9683 // Adding two lengths can't overflow. | 9695 // Adding two lengths can't overflow. |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9872 | 9884 |
9873 // Just jump to runtime to add the two strings. | 9885 // Just jump to runtime to add the two strings. |
9874 __ bind(&string_add_runtime); | 9886 __ bind(&string_add_runtime); |
9875 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 9887 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
9876 } | 9888 } |
9877 | 9889 |
9878 | 9890 |
9879 #undef __ | 9891 #undef __ |
9880 | 9892 |
9881 } } // namespace v8::internal | 9893 } } // namespace v8::internal |
OLD | NEW |