| 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 3960 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3971 ASSERT(kSmiTag == 0); | 3971 ASSERT(kSmiTag == 0); |
| 3972 __ tst(r0, Operand(kSmiTagMask | 0x80000000u)); | 3972 __ tst(r0, Operand(kSmiTagMask | 0x80000000u)); |
| 3973 __ b(ne, &slow); // The index was negative or not a Smi. | 3973 __ b(ne, &slow); // The index was negative or not a Smi. |
| 3974 | 3974 |
| 3975 __ bind(&try_again_with_new_string); | 3975 __ bind(&try_again_with_new_string); |
| 3976 __ CompareObjectType(r1, r2, r2, FIRST_NONSTRING_TYPE); | 3976 __ CompareObjectType(r1, r2, r2, FIRST_NONSTRING_TYPE); |
| 3977 __ b(ge, &slow); | 3977 __ b(ge, &slow); |
| 3978 | 3978 |
| 3979 // Now r2 has the string type. | 3979 // Now r2 has the string type. |
| 3980 __ ldr(r3, FieldMemOperand(r1, String::kLengthOffset)); | 3980 __ ldr(r3, FieldMemOperand(r1, String::kLengthOffset)); |
| 3981 // Now r3 has the length of the string. Compare with the index. | 3981 // Now r3 has the length of the string. Compare with the index. |
| 3982 __ cmp(r3, Operand(r0)); | 3982 __ cmp(r3, Operand(r0, LSR, kSmiTagSize)); |
| 3983 __ b(le, &slow); | 3983 __ b(le, &slow); |
| 3984 | 3984 |
| 3985 // Here we know the index is in range. Check that string is sequential. | 3985 // Here we know the index is in range. Check that string is sequential. |
| 3986 ASSERT_EQ(0, kSeqStringTag); | 3986 ASSERT_EQ(0, kSeqStringTag); |
| 3987 __ tst(r2, Operand(kStringRepresentationMask)); | 3987 __ tst(r2, Operand(kStringRepresentationMask)); |
| 3988 __ b(ne, ¬_a_flat_string); | 3988 __ b(ne, ¬_a_flat_string); |
| 3989 | 3989 |
| 3990 // Check whether it is an ASCII string. | 3990 // Check whether it is an ASCII string. |
| 3991 ASSERT_EQ(0, kTwoByteStringTag); | 3991 ASSERT_EQ(0, kTwoByteStringTag); |
| 3992 __ tst(r2, Operand(kStringEncodingMask)); | 3992 __ tst(r2, Operand(kStringEncodingMask)); |
| (...skipping 4388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8381 // Check that the second argument is a string. | 8381 // Check that the second argument is a string. |
| 8382 __ ldr(subject, MemOperand(sp, kSubjectOffset)); | 8382 __ ldr(subject, MemOperand(sp, kSubjectOffset)); |
| 8383 __ tst(subject, Operand(kSmiTagMask)); | 8383 __ tst(subject, Operand(kSmiTagMask)); |
| 8384 __ b(eq, &runtime); | 8384 __ b(eq, &runtime); |
| 8385 Condition is_string = masm->IsObjectStringType(subject, r0); | 8385 Condition is_string = masm->IsObjectStringType(subject, r0); |
| 8386 __ b(NegateCondition(is_string), &runtime); | 8386 __ b(NegateCondition(is_string), &runtime); |
| 8387 // Get the length of the string to r3. | 8387 // Get the length of the string to r3. |
| 8388 __ ldr(r3, FieldMemOperand(subject, String::kLengthOffset)); | 8388 __ ldr(r3, FieldMemOperand(subject, String::kLengthOffset)); |
| 8389 | 8389 |
| 8390 // r2: Number of capture registers | 8390 // r2: Number of capture registers |
| 8391 // r3: Length of subject string as a smi | 8391 // r3: Length of subject string |
| 8392 // subject: Subject string | 8392 // subject: Subject string |
| 8393 // regexp_data: RegExp data (FixedArray) | 8393 // regexp_data: RegExp data (FixedArray) |
| 8394 // Check that the third argument is a positive smi less than the subject | 8394 // Check that the third argument is a positive smi less than the subject |
| 8395 // string length. A negative value will be greater (unsigned comparison). | 8395 // string length. A negative value will be greater (unsigned comparison). |
| 8396 __ ldr(r0, MemOperand(sp, kPreviousIndexOffset)); | 8396 __ ldr(r0, MemOperand(sp, kPreviousIndexOffset)); |
| 8397 __ tst(r0, Operand(kSmiTagMask)); | 8397 __ cmp(r3, Operand(r0, ASR, kSmiTagSize + kSmiShiftSize)); |
| 8398 __ b(eq, &runtime); | 8398 __ b(ls, &runtime); |
| 8399 __ cmp(r3, Operand(r0)); | |
| 8400 __ b(le, &runtime); | |
| 8401 | 8399 |
| 8402 // r2: Number of capture registers | 8400 // r2: Number of capture registers |
| 8403 // subject: Subject string | 8401 // subject: Subject string |
| 8404 // regexp_data: RegExp data (FixedArray) | 8402 // regexp_data: RegExp data (FixedArray) |
| 8405 // Check that the fourth object is a JSArray object. | 8403 // Check that the fourth object is a JSArray object. |
| 8406 __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset)); | 8404 __ ldr(r0, MemOperand(sp, kLastMatchInfoOffset)); |
| 8407 __ tst(r0, Operand(kSmiTagMask)); | 8405 __ tst(r0, Operand(kSmiTagMask)); |
| 8408 __ b(eq, &runtime); | 8406 __ b(eq, &runtime); |
| 8409 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); | 8407 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); |
| 8410 __ b(ne, &runtime); | 8408 __ b(ne, &runtime); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8516 __ add(r0, r0, Operand(r2)); | 8514 __ add(r0, r0, Operand(r2)); |
| 8517 __ str(r0, MemOperand(sp, 1 * kPointerSize)); | 8515 __ str(r0, MemOperand(sp, 1 * kPointerSize)); |
| 8518 | 8516 |
| 8519 // Argument 5 (sp[0]): static offsets vector buffer. | 8517 // Argument 5 (sp[0]): static offsets vector buffer. |
| 8520 __ mov(r0, Operand(ExternalReference::address_of_static_offsets_vector())); | 8518 __ mov(r0, Operand(ExternalReference::address_of_static_offsets_vector())); |
| 8521 __ str(r0, MemOperand(sp, 0 * kPointerSize)); | 8519 __ str(r0, MemOperand(sp, 0 * kPointerSize)); |
| 8522 | 8520 |
| 8523 // For arguments 4 and 3 get string length, calculate start of string data and | 8521 // For arguments 4 and 3 get string length, calculate start of string data and |
| 8524 // calculate the shift of the index (0 for ASCII and 1 for two byte). | 8522 // calculate the shift of the index (0 for ASCII and 1 for two byte). |
| 8525 __ ldr(r0, FieldMemOperand(subject, String::kLengthOffset)); | 8523 __ ldr(r0, FieldMemOperand(subject, String::kLengthOffset)); |
| 8526 __ mov(r0, Operand(r0, ASR, kSmiTagSize)); | |
| 8527 ASSERT_EQ(SeqAsciiString::kHeaderSize, SeqTwoByteString::kHeaderSize); | 8524 ASSERT_EQ(SeqAsciiString::kHeaderSize, SeqTwoByteString::kHeaderSize); |
| 8528 __ add(r9, subject, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 8525 __ add(r9, subject, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
| 8529 __ eor(r3, r3, Operand(1)); | 8526 __ eor(r3, r3, Operand(1)); |
| 8530 // Argument 4 (r3): End of string data | 8527 // Argument 4 (r3): End of string data |
| 8531 // Argument 3 (r2): Start of string data | 8528 // Argument 3 (r2): Start of string data |
| 8532 __ add(r2, r9, Operand(r1, LSL, r3)); | 8529 __ add(r2, r9, Operand(r1, LSL, r3)); |
| 8533 __ add(r3, r9, Operand(r0, LSL, r3)); | 8530 __ add(r3, r9, Operand(r0, LSL, r3)); |
| 8534 | 8531 |
| 8535 // Argument 2 (r1): Previous index. | 8532 // Argument 2 (r1): Previous index. |
| 8536 // Already there | 8533 // Already there |
| (...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9024 candidate, | 9021 candidate, |
| 9025 LSL, | 9022 LSL, |
| 9026 kPointerSizeLog2)); | 9023 kPointerSizeLog2)); |
| 9027 | 9024 |
| 9028 // If entry is undefined no string with this hash can be found. | 9025 // If entry is undefined no string with this hash can be found. |
| 9029 __ cmp(candidate, undefined); | 9026 __ cmp(candidate, undefined); |
| 9030 __ b(eq, not_found); | 9027 __ b(eq, not_found); |
| 9031 | 9028 |
| 9032 // If length is not 2 the string is not a candidate. | 9029 // If length is not 2 the string is not a candidate. |
| 9033 __ ldr(scratch, FieldMemOperand(candidate, String::kLengthOffset)); | 9030 __ ldr(scratch, FieldMemOperand(candidate, String::kLengthOffset)); |
| 9034 __ cmp(scratch, Operand(Smi::FromInt(2))); | 9031 __ cmp(scratch, Operand(2)); |
| 9035 __ b(ne, &next_probe[i]); | 9032 __ b(ne, &next_probe[i]); |
| 9036 | 9033 |
| 9037 // Check that the candidate is a non-external ascii string. | 9034 // Check that the candidate is a non-external ascii string. |
| 9038 __ ldr(scratch, FieldMemOperand(candidate, HeapObject::kMapOffset)); | 9035 __ ldr(scratch, FieldMemOperand(candidate, HeapObject::kMapOffset)); |
| 9039 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | 9036 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
| 9040 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, | 9037 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, |
| 9041 &next_probe[i]); | 9038 &next_probe[i]); |
| 9042 | 9039 |
| 9043 // Check if the two characters match. | 9040 // Check if the two characters match. |
| 9044 // Assumes that word load is little endian. | 9041 // Assumes that word load is little endian. |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9175 // Definitly a sequential string. | 9172 // Definitly a sequential string. |
| 9176 __ bind(&seq_string); | 9173 __ bind(&seq_string); |
| 9177 | 9174 |
| 9178 // r1: instance type. | 9175 // r1: instance type. |
| 9179 // r2: length | 9176 // r2: length |
| 9180 // r3: from index (untaged smi) | 9177 // r3: from index (untaged smi) |
| 9181 // r5: string | 9178 // r5: string |
| 9182 // r6: from (smi) | 9179 // r6: from (smi) |
| 9183 // r7: to (smi) | 9180 // r7: to (smi) |
| 9184 __ ldr(r4, FieldMemOperand(r5, String::kLengthOffset)); | 9181 __ ldr(r4, FieldMemOperand(r5, String::kLengthOffset)); |
| 9185 __ cmp(r4, Operand(r7)); | 9182 __ cmp(r4, Operand(r7, ASR, 1)); |
| 9186 __ b(lt, &runtime); // Fail if to > length. | 9183 __ b(lt, &runtime); // Fail if to > length. |
| 9187 | 9184 |
| 9188 // r1: instance type. | 9185 // r1: instance type. |
| 9189 // r2: result string length. | 9186 // r2: result string length. |
| 9190 // r3: from index (untaged smi) | 9187 // r3: from index (untaged smi) |
| 9191 // r5: string. | 9188 // r5: string. |
| 9192 // r6: from offset (smi) | 9189 // r6: from offset (smi) |
| 9193 // Check for flat ascii string. | 9190 // Check for flat ascii string. |
| 9194 Label non_ascii_flat; | 9191 Label non_ascii_flat; |
| 9195 __ tst(r1, Operand(kStringEncodingMask)); | 9192 __ tst(r1, Operand(kStringEncodingMask)); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9294 Register scratch3, | 9291 Register scratch3, |
| 9295 Register scratch4) { | 9292 Register scratch4) { |
| 9296 Label compare_lengths; | 9293 Label compare_lengths; |
| 9297 // Find minimum length and length difference. | 9294 // Find minimum length and length difference. |
| 9298 __ ldr(scratch1, FieldMemOperand(left, String::kLengthOffset)); | 9295 __ ldr(scratch1, FieldMemOperand(left, String::kLengthOffset)); |
| 9299 __ ldr(scratch2, FieldMemOperand(right, String::kLengthOffset)); | 9296 __ ldr(scratch2, FieldMemOperand(right, String::kLengthOffset)); |
| 9300 __ sub(scratch3, scratch1, Operand(scratch2), SetCC); | 9297 __ sub(scratch3, scratch1, Operand(scratch2), SetCC); |
| 9301 Register length_delta = scratch3; | 9298 Register length_delta = scratch3; |
| 9302 __ mov(scratch1, scratch2, LeaveCC, gt); | 9299 __ mov(scratch1, scratch2, LeaveCC, gt); |
| 9303 Register min_length = scratch1; | 9300 Register min_length = scratch1; |
| 9304 ASSERT(kSmiTag == 0); | |
| 9305 __ tst(min_length, Operand(min_length)); | 9301 __ tst(min_length, Operand(min_length)); |
| 9306 __ b(eq, &compare_lengths); | 9302 __ b(eq, &compare_lengths); |
| 9307 | 9303 |
| 9308 // Untag smi. | |
| 9309 __ mov(min_length, Operand(min_length, ASR, kSmiTagSize)); | |
| 9310 | |
| 9311 // Setup registers so that we only need to increment one register | 9304 // Setup registers so that we only need to increment one register |
| 9312 // in the loop. | 9305 // in the loop. |
| 9313 __ add(scratch2, min_length, | 9306 __ add(scratch2, min_length, |
| 9314 Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 9307 Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
| 9315 __ add(left, left, Operand(scratch2)); | 9308 __ add(left, left, Operand(scratch2)); |
| 9316 __ add(right, right, Operand(scratch2)); | 9309 __ add(right, right, Operand(scratch2)); |
| 9317 // Registers left and right points to the min_length character of strings. | 9310 // Registers left and right points to the min_length character of strings. |
| 9318 __ rsb(min_length, min_length, Operand(-1)); | 9311 __ rsb(min_length, min_length, Operand(-1)); |
| 9319 Register index = min_length; | 9312 Register index = min_length; |
| 9320 // Index starts at -min_length. | 9313 // Index starts at -min_length. |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9410 // Both arguments are strings. | 9403 // Both arguments are strings. |
| 9411 // r0: first string | 9404 // r0: first string |
| 9412 // r1: second string | 9405 // r1: second string |
| 9413 // r4: first string instance type (if string_check_) | 9406 // r4: first string instance type (if string_check_) |
| 9414 // r5: second string instance type (if string_check_) | 9407 // r5: second string instance type (if string_check_) |
| 9415 { | 9408 { |
| 9416 Label strings_not_empty; | 9409 Label strings_not_empty; |
| 9417 // Check if either of the strings are empty. In that case return the other. | 9410 // Check if either of the strings are empty. In that case return the other. |
| 9418 __ ldr(r2, FieldMemOperand(r0, String::kLengthOffset)); | 9411 __ ldr(r2, FieldMemOperand(r0, String::kLengthOffset)); |
| 9419 __ ldr(r3, FieldMemOperand(r1, String::kLengthOffset)); | 9412 __ ldr(r3, FieldMemOperand(r1, String::kLengthOffset)); |
| 9420 ASSERT(kSmiTag == 0); | 9413 __ cmp(r2, Operand(0)); // Test if first string is empty. |
| 9421 __ cmp(r2, Operand(Smi::FromInt(0))); // Test if first string is empty. | |
| 9422 __ mov(r0, Operand(r1), LeaveCC, eq); // If first is empty, return second. | 9414 __ mov(r0, Operand(r1), LeaveCC, eq); // If first is empty, return second. |
| 9423 ASSERT(kSmiTag == 0); | 9415 __ cmp(r3, Operand(0), ne); // Else test if second string is empty. |
| 9424 // Else test if second string is empty. | |
| 9425 __ cmp(r3, Operand(Smi::FromInt(0)), ne); | |
| 9426 __ b(ne, &strings_not_empty); // If either string was empty, return r0. | 9416 __ b(ne, &strings_not_empty); // If either string was empty, return r0. |
| 9427 | 9417 |
| 9428 __ IncrementCounter(&Counters::string_add_native, 1, r2, r3); | 9418 __ IncrementCounter(&Counters::string_add_native, 1, r2, r3); |
| 9429 __ add(sp, sp, Operand(2 * kPointerSize)); | 9419 __ add(sp, sp, Operand(2 * kPointerSize)); |
| 9430 __ Ret(); | 9420 __ Ret(); |
| 9431 | 9421 |
| 9432 __ bind(&strings_not_empty); | 9422 __ bind(&strings_not_empty); |
| 9433 } | 9423 } |
| 9434 | 9424 |
| 9435 __ mov(r2, Operand(r2, ASR, kSmiTagSize)); | |
| 9436 __ mov(r3, Operand(r3, ASR, kSmiTagSize)); | |
| 9437 // Both strings are non-empty. | 9425 // Both strings are non-empty. |
| 9438 // r0: first string | 9426 // r0: first string |
| 9439 // r1: second string | 9427 // r1: second string |
| 9440 // r2: length of first string | 9428 // r2: length of first string |
| 9441 // r3: length of second string | 9429 // r3: length of second string |
| 9442 // r4: first string instance type (if string_check_) | 9430 // r4: first string instance type (if string_check_) |
| 9443 // r5: second string instance type (if string_check_) | 9431 // r5: second string instance type (if string_check_) |
| 9444 // Look at the length of the result of adding the two strings. | 9432 // Look at the length of the result of adding the two strings. |
| 9445 Label string_add_flat_result, longer_than_two; | 9433 Label string_add_flat_result, longer_than_two; |
| 9446 // Adding two lengths can't overflow. | 9434 // Adding two lengths can't overflow. |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9635 | 9623 |
| 9636 // Just jump to runtime to add the two strings. | 9624 // Just jump to runtime to add the two strings. |
| 9637 __ bind(&string_add_runtime); | 9625 __ bind(&string_add_runtime); |
| 9638 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 9626 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
| 9639 } | 9627 } |
| 9640 | 9628 |
| 9641 | 9629 |
| 9642 #undef __ | 9630 #undef __ |
| 9643 | 9631 |
| 9644 } } // namespace v8::internal | 9632 } } // namespace v8::internal |
| OLD | NEW |