OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 5105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5116 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); | 5116 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); |
5117 if (FLAG_debug_code) { | 5117 if (FLAG_debug_code) { |
5118 // Assert that we do not have a cons or slice (indirect strings) here. | 5118 // Assert that we do not have a cons or slice (indirect strings) here. |
5119 // Sequential strings have already been ruled out. | 5119 // Sequential strings have already been ruled out. |
5120 __ tst(r0, Operand(kIsIndirectStringMask)); | 5120 __ tst(r0, Operand(kIsIndirectStringMask)); |
5121 __ Assert(eq, "external string expected, but not found"); | 5121 __ Assert(eq, "external string expected, but not found"); |
5122 } | 5122 } |
5123 __ ldr(subject, | 5123 __ ldr(subject, |
5124 FieldMemOperand(subject, ExternalString::kResourceDataOffset)); | 5124 FieldMemOperand(subject, ExternalString::kResourceDataOffset)); |
5125 // Move the pointer so that offset-wise, it looks like a sequential string. | 5125 // Move the pointer so that offset-wise, it looks like a sequential string. |
5126 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); | 5126 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); |
5127 __ sub(subject, | 5127 __ sub(subject, |
5128 subject, | 5128 subject, |
5129 Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 5129 Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
5130 __ jmp(&seq_string); | 5130 __ jmp(&seq_string); |
5131 | 5131 |
5132 // Do the runtime call to execute the regexp. | 5132 // Do the runtime call to execute the regexp. |
5133 __ bind(&runtime); | 5133 __ bind(&runtime); |
5134 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); | 5134 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
5135 #endif // V8_INTERPRETED_REGEXP | 5135 #endif // V8_INTERPRETED_REGEXP |
5136 } | 5136 } |
(...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5843 // operation. | 5843 // operation. |
5844 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &next_probe[i]); | 5844 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &next_probe[i]); |
5845 | 5845 |
5846 // If length is not 2 the string is not a candidate. | 5846 // If length is not 2 the string is not a candidate. |
5847 __ ldr(scratch, FieldMemOperand(candidate, String::kLengthOffset)); | 5847 __ ldr(scratch, FieldMemOperand(candidate, String::kLengthOffset)); |
5848 __ cmp(scratch, Operand(Smi::FromInt(2))); | 5848 __ cmp(scratch, Operand(Smi::FromInt(2))); |
5849 __ b(ne, &next_probe[i]); | 5849 __ b(ne, &next_probe[i]); |
5850 | 5850 |
5851 // Check if the two characters match. | 5851 // Check if the two characters match. |
5852 // Assumes that word load is little endian. | 5852 // Assumes that word load is little endian. |
5853 __ ldrh(scratch, FieldMemOperand(candidate, SeqAsciiString::kHeaderSize)); | 5853 __ ldrh(scratch, FieldMemOperand(candidate, SeqOneByteString::kHeaderSize)); |
5854 __ cmp(chars, scratch); | 5854 __ cmp(chars, scratch); |
5855 __ b(eq, &found_in_symbol_table); | 5855 __ b(eq, &found_in_symbol_table); |
5856 __ bind(&next_probe[i]); | 5856 __ bind(&next_probe[i]); |
5857 } | 5857 } |
5858 | 5858 |
5859 // No matching 2 character string found by probing. | 5859 // No matching 2 character string found by probing. |
5860 __ jmp(not_found); | 5860 __ jmp(not_found); |
5861 | 5861 |
5862 // Scratch register contains result when we fall through to here. | 5862 // Scratch register contains result when we fall through to here. |
5863 Register result = candidate; | 5863 Register result = candidate; |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6056 // Rule out short external strings. | 6056 // Rule out short external strings. |
6057 STATIC_CHECK(kShortExternalStringTag != 0); | 6057 STATIC_CHECK(kShortExternalStringTag != 0); |
6058 __ tst(r1, Operand(kShortExternalStringTag)); | 6058 __ tst(r1, Operand(kShortExternalStringTag)); |
6059 __ b(ne, &runtime); | 6059 __ b(ne, &runtime); |
6060 __ ldr(r5, FieldMemOperand(r5, ExternalString::kResourceDataOffset)); | 6060 __ ldr(r5, FieldMemOperand(r5, ExternalString::kResourceDataOffset)); |
6061 // r5 already points to the first character of underlying string. | 6061 // r5 already points to the first character of underlying string. |
6062 __ jmp(&allocate_result); | 6062 __ jmp(&allocate_result); |
6063 | 6063 |
6064 __ bind(&sequential_string); | 6064 __ bind(&sequential_string); |
6065 // Locate first character of underlying subject string. | 6065 // Locate first character of underlying subject string. |
6066 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); | 6066 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); |
6067 __ add(r5, r5, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 6067 __ add(r5, r5, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
6068 | 6068 |
6069 __ bind(&allocate_result); | 6069 __ bind(&allocate_result); |
6070 // Sequential acii string. Allocate the result. | 6070 // Sequential acii string. Allocate the result. |
6071 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); | 6071 STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0); |
6072 __ tst(r1, Operand(kStringEncodingMask)); | 6072 __ tst(r1, Operand(kStringEncodingMask)); |
6073 __ b(eq, &two_byte_sequential); | 6073 __ b(eq, &two_byte_sequential); |
6074 | 6074 |
6075 // Allocate and copy the resulting ASCII string. | 6075 // Allocate and copy the resulting ASCII string. |
6076 __ AllocateAsciiString(r0, r2, r4, r6, r7, &runtime); | 6076 __ AllocateAsciiString(r0, r2, r4, r6, r7, &runtime); |
6077 | 6077 |
6078 // Locate first character of substring to copy. | 6078 // Locate first character of substring to copy. |
6079 __ add(r5, r5, r3); | 6079 __ add(r5, r5, r3); |
6080 // Locate first character of result. | 6080 // Locate first character of result. |
6081 __ add(r1, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 6081 __ add(r1, r0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
6082 | 6082 |
6083 // r0: result string | 6083 // r0: result string |
6084 // r1: first character of result string | 6084 // r1: first character of result string |
6085 // r2: result string length | 6085 // r2: result string length |
6086 // r5: first character of substring to copy | 6086 // r5: first character of substring to copy |
6087 STATIC_ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0); | 6087 STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); |
6088 StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9, | 6088 StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9, |
6089 COPY_ASCII | DEST_ALWAYS_ALIGNED); | 6089 COPY_ASCII | DEST_ALWAYS_ALIGNED); |
6090 __ jmp(&return_r0); | 6090 __ jmp(&return_r0); |
6091 | 6091 |
6092 // Allocate and copy the resulting two-byte string. | 6092 // Allocate and copy the resulting two-byte string. |
6093 __ bind(&two_byte_sequential); | 6093 __ bind(&two_byte_sequential); |
6094 __ AllocateTwoByteString(r0, r2, r4, r6, r7, &runtime); | 6094 __ AllocateTwoByteString(r0, r2, r4, r6, r7, &runtime); |
6095 | 6095 |
6096 // Locate first character of substring to copy. | 6096 // Locate first character of substring to copy. |
6097 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); | 6097 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6202 Register right, | 6202 Register right, |
6203 Register length, | 6203 Register length, |
6204 Register scratch1, | 6204 Register scratch1, |
6205 Register scratch2, | 6205 Register scratch2, |
6206 Label* chars_not_equal) { | 6206 Label* chars_not_equal) { |
6207 // Change index to run from -length to -1 by adding length to string | 6207 // Change index to run from -length to -1 by adding length to string |
6208 // start. This means that loop ends when index reaches zero, which | 6208 // start. This means that loop ends when index reaches zero, which |
6209 // doesn't need an additional compare. | 6209 // doesn't need an additional compare. |
6210 __ SmiUntag(length); | 6210 __ SmiUntag(length); |
6211 __ add(scratch1, length, | 6211 __ add(scratch1, length, |
6212 Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 6212 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
6213 __ add(left, left, Operand(scratch1)); | 6213 __ add(left, left, Operand(scratch1)); |
6214 __ add(right, right, Operand(scratch1)); | 6214 __ add(right, right, Operand(scratch1)); |
6215 __ rsb(length, length, Operand::Zero()); | 6215 __ rsb(length, length, Operand::Zero()); |
6216 Register index = length; // index = -length; | 6216 Register index = length; // index = -length; |
6217 | 6217 |
6218 // Compare loop. | 6218 // Compare loop. |
6219 Label loop; | 6219 Label loop; |
6220 __ bind(&loop); | 6220 __ bind(&loop); |
6221 __ ldrb(scratch1, MemOperand(left, index)); | 6221 __ ldrb(scratch1, MemOperand(left, index)); |
6222 __ ldrb(scratch2, MemOperand(right, index)); | 6222 __ ldrb(scratch2, MemOperand(right, index)); |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6355 if (flags_ != NO_STRING_ADD_FLAGS) { | 6355 if (flags_ != NO_STRING_ADD_FLAGS) { |
6356 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); | 6356 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); |
6357 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); | 6357 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); |
6358 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); | 6358 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); |
6359 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); | 6359 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); |
6360 } | 6360 } |
6361 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r7, | 6361 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r7, |
6362 &call_runtime); | 6362 &call_runtime); |
6363 | 6363 |
6364 // Get the two characters forming the sub string. | 6364 // Get the two characters forming the sub string. |
6365 __ ldrb(r2, FieldMemOperand(r0, SeqAsciiString::kHeaderSize)); | 6365 __ ldrb(r2, FieldMemOperand(r0, SeqOneByteString::kHeaderSize)); |
6366 __ ldrb(r3, FieldMemOperand(r1, SeqAsciiString::kHeaderSize)); | 6366 __ ldrb(r3, FieldMemOperand(r1, SeqOneByteString::kHeaderSize)); |
6367 | 6367 |
6368 // Try to lookup two character string in symbol table. If it is not found | 6368 // Try to lookup two character string in symbol table. If it is not found |
6369 // just allocate a new one. | 6369 // just allocate a new one. |
6370 Label make_two_character_string; | 6370 Label make_two_character_string; |
6371 StringHelper::GenerateTwoCharacterSymbolTableProbe( | 6371 StringHelper::GenerateTwoCharacterSymbolTableProbe( |
6372 masm, r2, r3, r6, r7, r4, r5, r9, &make_two_character_string); | 6372 masm, r2, r3, r6, r7, r4, r5, r9, &make_two_character_string); |
6373 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); | 6373 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); |
6374 __ add(sp, sp, Operand(2 * kPointerSize)); | 6374 __ add(sp, sp, Operand(2 * kPointerSize)); |
6375 __ Ret(); | 6375 __ Ret(); |
6376 | 6376 |
6377 __ bind(&make_two_character_string); | 6377 __ bind(&make_two_character_string); |
6378 // Resulting string has length 2 and first chars of two strings | 6378 // Resulting string has length 2 and first chars of two strings |
6379 // are combined into single halfword in r2 register. | 6379 // are combined into single halfword in r2 register. |
6380 // So we can fill resulting string without two loops by a single | 6380 // So we can fill resulting string without two loops by a single |
6381 // halfword store instruction (which assumes that processor is | 6381 // halfword store instruction (which assumes that processor is |
6382 // in a little endian mode) | 6382 // in a little endian mode) |
6383 __ mov(r6, Operand(2)); | 6383 __ mov(r6, Operand(2)); |
6384 __ AllocateAsciiString(r0, r6, r4, r5, r9, &call_runtime); | 6384 __ AllocateAsciiString(r0, r6, r4, r5, r9, &call_runtime); |
6385 __ strh(r2, FieldMemOperand(r0, SeqAsciiString::kHeaderSize)); | 6385 __ strh(r2, FieldMemOperand(r0, SeqOneByteString::kHeaderSize)); |
6386 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); | 6386 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); |
6387 __ add(sp, sp, Operand(2 * kPointerSize)); | 6387 __ add(sp, sp, Operand(2 * kPointerSize)); |
6388 __ Ret(); | 6388 __ Ret(); |
6389 | 6389 |
6390 __ bind(&longer_than_two); | 6390 __ bind(&longer_than_two); |
6391 // Check if resulting string will be flat. | 6391 // Check if resulting string will be flat. |
6392 __ cmp(r6, Operand(ConsString::kMinLength)); | 6392 __ cmp(r6, Operand(ConsString::kMinLength)); |
6393 __ b(lt, &string_add_flat_result); | 6393 __ b(lt, &string_add_flat_result); |
6394 // Handle exceptionally long strings in the runtime system. | 6394 // Handle exceptionally long strings in the runtime system. |
6395 STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0); | 6395 STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6457 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); | 6457 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); |
6458 } | 6458 } |
6459 | 6459 |
6460 // Check whether both strings have same encoding | 6460 // Check whether both strings have same encoding |
6461 __ eor(r7, r4, Operand(r5)); | 6461 __ eor(r7, r4, Operand(r5)); |
6462 __ tst(r7, Operand(kStringEncodingMask)); | 6462 __ tst(r7, Operand(kStringEncodingMask)); |
6463 __ b(ne, &call_runtime); | 6463 __ b(ne, &call_runtime); |
6464 | 6464 |
6465 STATIC_ASSERT(kSeqStringTag == 0); | 6465 STATIC_ASSERT(kSeqStringTag == 0); |
6466 __ tst(r4, Operand(kStringRepresentationMask)); | 6466 __ tst(r4, Operand(kStringRepresentationMask)); |
6467 STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize); | 6467 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize); |
6468 __ add(r7, | 6468 __ add(r7, |
6469 r0, | 6469 r0, |
6470 Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag), | 6470 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag), |
6471 LeaveCC, | 6471 LeaveCC, |
6472 eq); | 6472 eq); |
6473 __ b(eq, &first_prepared); | 6473 __ b(eq, &first_prepared); |
6474 // External string: rule out short external string and load string resource. | 6474 // External string: rule out short external string and load string resource. |
6475 STATIC_ASSERT(kShortExternalStringTag != 0); | 6475 STATIC_ASSERT(kShortExternalStringTag != 0); |
6476 __ tst(r4, Operand(kShortExternalStringMask)); | 6476 __ tst(r4, Operand(kShortExternalStringMask)); |
6477 __ b(ne, &call_runtime); | 6477 __ b(ne, &call_runtime); |
6478 __ ldr(r7, FieldMemOperand(r0, ExternalString::kResourceDataOffset)); | 6478 __ ldr(r7, FieldMemOperand(r0, ExternalString::kResourceDataOffset)); |
6479 __ bind(&first_prepared); | 6479 __ bind(&first_prepared); |
6480 | 6480 |
6481 STATIC_ASSERT(kSeqStringTag == 0); | 6481 STATIC_ASSERT(kSeqStringTag == 0); |
6482 __ tst(r5, Operand(kStringRepresentationMask)); | 6482 __ tst(r5, Operand(kStringRepresentationMask)); |
6483 STATIC_ASSERT(SeqAsciiString::kHeaderSize == SeqTwoByteString::kHeaderSize); | 6483 STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize); |
6484 __ add(r1, | 6484 __ add(r1, |
6485 r1, | 6485 r1, |
6486 Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag), | 6486 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag), |
6487 LeaveCC, | 6487 LeaveCC, |
6488 eq); | 6488 eq); |
6489 __ b(eq, &second_prepared); | 6489 __ b(eq, &second_prepared); |
6490 // External string: rule out short external string and load string resource. | 6490 // External string: rule out short external string and load string resource. |
6491 STATIC_ASSERT(kShortExternalStringTag != 0); | 6491 STATIC_ASSERT(kShortExternalStringTag != 0); |
6492 __ tst(r5, Operand(kShortExternalStringMask)); | 6492 __ tst(r5, Operand(kShortExternalStringMask)); |
6493 __ b(ne, &call_runtime); | 6493 __ b(ne, &call_runtime); |
6494 __ ldr(r1, FieldMemOperand(r1, ExternalString::kResourceDataOffset)); | 6494 __ ldr(r1, FieldMemOperand(r1, ExternalString::kResourceDataOffset)); |
6495 __ bind(&second_prepared); | 6495 __ bind(&second_prepared); |
6496 | 6496 |
6497 Label non_ascii_string_add_flat_result; | 6497 Label non_ascii_string_add_flat_result; |
6498 // r7: first character of first string | 6498 // r7: first character of first string |
6499 // r1: first character of second string | 6499 // r1: first character of second string |
6500 // r2: length of first string. | 6500 // r2: length of first string. |
6501 // r3: length of second string. | 6501 // r3: length of second string. |
6502 // r6: sum of lengths. | 6502 // r6: sum of lengths. |
6503 // Both strings have the same encoding. | 6503 // Both strings have the same encoding. |
6504 STATIC_ASSERT(kTwoByteStringTag == 0); | 6504 STATIC_ASSERT(kTwoByteStringTag == 0); |
6505 __ tst(r5, Operand(kStringEncodingMask)); | 6505 __ tst(r5, Operand(kStringEncodingMask)); |
6506 __ b(eq, &non_ascii_string_add_flat_result); | 6506 __ b(eq, &non_ascii_string_add_flat_result); |
6507 | 6507 |
6508 __ AllocateAsciiString(r0, r6, r4, r5, r9, &call_runtime); | 6508 __ AllocateAsciiString(r0, r6, r4, r5, r9, &call_runtime); |
6509 __ add(r6, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 6509 __ add(r6, r0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
6510 // r0: result string. | 6510 // r0: result string. |
6511 // r7: first character of first string. | 6511 // r7: first character of first string. |
6512 // r1: first character of second string. | 6512 // r1: first character of second string. |
6513 // r2: length of first string. | 6513 // r2: length of first string. |
6514 // r3: length of second string. | 6514 // r3: length of second string. |
6515 // r6: first character of result. | 6515 // r6: first character of result. |
6516 StringHelper::GenerateCopyCharacters(masm, r6, r7, r2, r4, true); | 6516 StringHelper::GenerateCopyCharacters(masm, r6, r7, r2, r4, true); |
6517 // r6: next character of result. | 6517 // r6: next character of result. |
6518 StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, true); | 6518 StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, true); |
6519 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); | 6519 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); |
(...skipping 1062 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7582 | 7582 |
7583 __ Pop(lr, r5, r1); | 7583 __ Pop(lr, r5, r1); |
7584 __ Ret(); | 7584 __ Ret(); |
7585 } | 7585 } |
7586 | 7586 |
7587 #undef __ | 7587 #undef __ |
7588 | 7588 |
7589 } } // namespace v8::internal | 7589 } } // namespace v8::internal |
7590 | 7590 |
7591 #endif // V8_TARGET_ARCH_ARM | 7591 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |