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 |