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 5228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5239 | 5239 |
5240 | 5240 |
5241 void StringCharAtGenerator::GenerateSlow( | 5241 void StringCharAtGenerator::GenerateSlow( |
5242 MacroAssembler* masm, | 5242 MacroAssembler* masm, |
5243 const RuntimeCallHelper& call_helper) { | 5243 const RuntimeCallHelper& call_helper) { |
5244 char_code_at_generator_.GenerateSlow(masm, call_helper); | 5244 char_code_at_generator_.GenerateSlow(masm, call_helper); |
5245 char_from_code_generator_.GenerateSlow(masm, call_helper); | 5245 char_from_code_generator_.GenerateSlow(masm, call_helper); |
5246 } | 5246 } |
5247 | 5247 |
5248 | 5248 |
5249 class StringHelper : public AllStatic { | |
5250 public: | |
5251 // Generate code for copying characters using a simple loop. This should only | |
5252 // be used in places where the number of characters is small and the | |
5253 // additional setup and checking in GenerateCopyCharactersLong adds too much | |
5254 // overhead. Copying of overlapping regions is not supported. | |
5255 // Dest register ends at the position after the last character written. | |
5256 static void GenerateCopyCharacters(MacroAssembler* masm, | |
5257 Register dest, | |
5258 Register src, | |
5259 Register count, | |
5260 Register scratch, | |
5261 bool ascii); | |
5262 | |
5263 // Generate code for copying a large number of characters. This function | |
5264 // is allowed to spend extra time setting up conditions to make copying | |
5265 // faster. Copying of overlapping regions is not supported. | |
5266 // Dest register ends at the position after the last character written. | |
5267 static void GenerateCopyCharactersLong(MacroAssembler* masm, | |
5268 Register dest, | |
5269 Register src, | |
5270 Register count, | |
5271 Register scratch1, | |
5272 Register scratch2, | |
5273 Register scratch3, | |
5274 Register scratch4, | |
5275 Register scratch5, | |
5276 int flags); | |
5277 | |
5278 | |
5279 // Probe the symbol table for a two character string. If the string is | |
5280 // not found by probing a jump to the label not_found is performed. This jump | |
5281 // does not guarantee that the string is not in the symbol table. If the | |
5282 // string is found the code falls through with the string in register r0. | |
5283 // Contents of both c1 and c2 registers are modified. At the exit c1 is | |
5284 // guaranteed to contain halfword with low and high bytes equal to | |
5285 // initial contents of c1 and c2 respectively. | |
5286 static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, | |
5287 Register c1, | |
5288 Register c2, | |
5289 Register scratch1, | |
5290 Register scratch2, | |
5291 Register scratch3, | |
5292 Register scratch4, | |
5293 Register scratch5, | |
5294 Label* not_found); | |
5295 | |
5296 // Generate string hash. | |
5297 static void GenerateHashInit(MacroAssembler* masm, | |
5298 Register hash, | |
5299 Register character); | |
5300 | |
5301 static void GenerateHashAddCharacter(MacroAssembler* masm, | |
5302 Register hash, | |
5303 Register character); | |
5304 | |
5305 static void GenerateHashGetHash(MacroAssembler* masm, | |
5306 Register hash); | |
5307 | |
5308 private: | |
5309 DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper); | |
5310 }; | |
5311 | |
5312 | |
5313 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, | 5249 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, |
5314 Register dest, | 5250 Register dest, |
5315 Register src, | 5251 Register src, |
5316 Register count, | 5252 Register count, |
5317 Register scratch, | 5253 Register scratch, |
5318 bool ascii) { | 5254 bool ascii) { |
5319 Label loop; | 5255 Label loop; |
5320 Label done; | 5256 Label done; |
5321 // This loop just copies one character at a time, as it is only used for very | 5257 // This loop just copies one character at a time, as it is only used for very |
5322 // short strings. | 5258 // short strings. |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5555 // mask: capacity mask | 5491 // mask: capacity mask |
5556 // first_symbol_table_element: address of the first element of | 5492 // first_symbol_table_element: address of the first element of |
5557 // the symbol table | 5493 // the symbol table |
5558 // undefined: the undefined object | 5494 // undefined: the undefined object |
5559 // scratch: - | 5495 // scratch: - |
5560 | 5496 |
5561 // Perform a number of probes in the symbol table. | 5497 // Perform a number of probes in the symbol table. |
5562 static const int kProbes = 4; | 5498 static const int kProbes = 4; |
5563 Label found_in_symbol_table; | 5499 Label found_in_symbol_table; |
5564 Label next_probe[kProbes]; | 5500 Label next_probe[kProbes]; |
| 5501 Register candidate = scratch5; // Scratch register contains candidate. |
5565 for (int i = 0; i < kProbes; i++) { | 5502 for (int i = 0; i < kProbes; i++) { |
5566 Register candidate = scratch5; // Scratch register contains candidate. | |
5567 | |
5568 // Calculate entry in symbol table. | 5503 // Calculate entry in symbol table. |
5569 if (i > 0) { | 5504 if (i > 0) { |
5570 __ add(candidate, hash, Operand(SymbolTable::GetProbeOffset(i))); | 5505 __ add(candidate, hash, Operand(SymbolTable::GetProbeOffset(i))); |
5571 } else { | 5506 } else { |
5572 __ mov(candidate, hash); | 5507 __ mov(candidate, hash); |
5573 } | 5508 } |
5574 | 5509 |
5575 __ and_(candidate, candidate, Operand(mask)); | 5510 __ and_(candidate, candidate, Operand(mask)); |
5576 | 5511 |
5577 // Load the entry from the symble table. | 5512 // Load the entry from the symble table. |
5578 STATIC_ASSERT(SymbolTable::kEntrySize == 1); | 5513 STATIC_ASSERT(SymbolTable::kEntrySize == 1); |
5579 __ ldr(candidate, | 5514 __ ldr(candidate, |
5580 MemOperand(first_symbol_table_element, | 5515 MemOperand(first_symbol_table_element, |
5581 candidate, | 5516 candidate, |
5582 LSL, | 5517 LSL, |
5583 kPointerSizeLog2)); | 5518 kPointerSizeLog2)); |
5584 | 5519 |
5585 // If entry is undefined no string with this hash can be found. | 5520 // If entry is undefined no string with this hash can be found. |
5586 Label is_string; | 5521 Label is_string; |
5587 __ CompareObjectType(candidate, scratch, scratch, ODDBALL_TYPE); | 5522 __ CompareObjectType(candidate, scratch, scratch, ODDBALL_TYPE); |
5588 __ b(ne, &is_string); | 5523 __ b(ne, &is_string); |
5589 | 5524 |
5590 __ cmp(undefined, candidate); | 5525 __ cmp(undefined, candidate); |
5591 __ b(eq, not_found); | 5526 __ b(eq, not_found); |
5592 // Must be null (deleted entry). | 5527 // Must be the hole (deleted entry). |
5593 if (FLAG_debug_code) { | 5528 if (FLAG_debug_code) { |
5594 __ LoadRoot(ip, Heap::kNullValueRootIndex); | 5529 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
5595 __ cmp(ip, candidate); | 5530 __ cmp(ip, candidate); |
5596 __ Assert(eq, "oddball in symbol table is not undefined or null"); | 5531 __ Assert(eq, "oddball in symbol table is not undefined or the hole"); |
5597 } | 5532 } |
5598 __ jmp(&next_probe[i]); | 5533 __ jmp(&next_probe[i]); |
5599 | 5534 |
5600 __ bind(&is_string); | 5535 __ bind(&is_string); |
5601 | 5536 |
5602 // Check that the candidate is a non-external ASCII string. The instance | 5537 // Check that the candidate is a non-external ASCII string. The instance |
5603 // type is still in the scratch register from the CompareObjectType | 5538 // type is still in the scratch register from the CompareObjectType |
5604 // operation. | 5539 // operation. |
5605 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &next_probe[i]); | 5540 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &next_probe[i]); |
5606 | 5541 |
5607 // If length is not 2 the string is not a candidate. | 5542 // If length is not 2 the string is not a candidate. |
5608 __ ldr(scratch, FieldMemOperand(candidate, String::kLengthOffset)); | 5543 __ ldr(scratch, FieldMemOperand(candidate, String::kLengthOffset)); |
5609 __ cmp(scratch, Operand(Smi::FromInt(2))); | 5544 __ cmp(scratch, Operand(Smi::FromInt(2))); |
5610 __ b(ne, &next_probe[i]); | 5545 __ b(ne, &next_probe[i]); |
5611 | 5546 |
5612 // Check if the two characters match. | 5547 // Check if the two characters match. |
5613 // Assumes that word load is little endian. | 5548 // Assumes that word load is little endian. |
5614 __ ldrh(scratch, FieldMemOperand(candidate, SeqAsciiString::kHeaderSize)); | 5549 __ ldrh(scratch, FieldMemOperand(candidate, SeqAsciiString::kHeaderSize)); |
5615 __ cmp(chars, scratch); | 5550 __ cmp(chars, scratch); |
5616 __ b(eq, &found_in_symbol_table); | 5551 __ b(eq, &found_in_symbol_table); |
5617 __ bind(&next_probe[i]); | 5552 __ bind(&next_probe[i]); |
5618 } | 5553 } |
5619 | 5554 |
5620 // No matching 2 character string found by probing. | 5555 // No matching 2 character string found by probing. |
5621 __ jmp(not_found); | 5556 __ jmp(not_found); |
5622 | 5557 |
5623 // Scratch register contains result when we fall through to here. | 5558 // Scratch register contains result when we fall through to here. |
5624 Register result = scratch; | 5559 Register result = candidate; |
5625 __ bind(&found_in_symbol_table); | 5560 __ bind(&found_in_symbol_table); |
5626 __ Move(r0, result); | 5561 __ Move(r0, result); |
5627 } | 5562 } |
5628 | 5563 |
5629 | 5564 |
5630 void StringHelper::GenerateHashInit(MacroAssembler* masm, | 5565 void StringHelper::GenerateHashInit(MacroAssembler* masm, |
5631 Register hash, | 5566 Register hash, |
5632 Register character) { | 5567 Register character) { |
5633 // hash = character + (character << 10); | 5568 // hash = character + (character << 10); |
5634 __ add(hash, character, Operand(character, LSL, 10)); | 5569 __ add(hash, character, Operand(character, LSL, 10)); |
5635 // hash ^= hash >> 6; | 5570 // hash ^= hash >> 6; |
5636 __ eor(hash, hash, Operand(hash, ASR, 6)); | 5571 __ eor(hash, hash, Operand(hash, LSR, 6)); |
5637 } | 5572 } |
5638 | 5573 |
5639 | 5574 |
5640 void StringHelper::GenerateHashAddCharacter(MacroAssembler* masm, | 5575 void StringHelper::GenerateHashAddCharacter(MacroAssembler* masm, |
5641 Register hash, | 5576 Register hash, |
5642 Register character) { | 5577 Register character) { |
5643 // hash += character; | 5578 // hash += character; |
5644 __ add(hash, hash, Operand(character)); | 5579 __ add(hash, hash, Operand(character)); |
5645 // hash += hash << 10; | 5580 // hash += hash << 10; |
5646 __ add(hash, hash, Operand(hash, LSL, 10)); | 5581 __ add(hash, hash, Operand(hash, LSL, 10)); |
5647 // hash ^= hash >> 6; | 5582 // hash ^= hash >> 6; |
5648 __ eor(hash, hash, Operand(hash, ASR, 6)); | 5583 __ eor(hash, hash, Operand(hash, LSR, 6)); |
5649 } | 5584 } |
5650 | 5585 |
5651 | 5586 |
5652 void StringHelper::GenerateHashGetHash(MacroAssembler* masm, | 5587 void StringHelper::GenerateHashGetHash(MacroAssembler* masm, |
5653 Register hash) { | 5588 Register hash) { |
5654 // hash += hash << 3; | 5589 // hash += hash << 3; |
5655 __ add(hash, hash, Operand(hash, LSL, 3)); | 5590 __ add(hash, hash, Operand(hash, LSL, 3)); |
5656 // hash ^= hash >> 11; | 5591 // hash ^= hash >> 11; |
5657 __ eor(hash, hash, Operand(hash, ASR, 11)); | 5592 __ eor(hash, hash, Operand(hash, LSR, 11)); |
5658 // hash += hash << 15; | 5593 // hash += hash << 15; |
5659 __ add(hash, hash, Operand(hash, LSL, 15), SetCC); | 5594 __ add(hash, hash, Operand(hash, LSL, 15), SetCC); |
5660 | 5595 |
| 5596 uint32_t kHashShiftCutOffMask = (1 << (32 - String::kHashShift)) - 1; |
| 5597 __ and_(hash, hash, Operand(kHashShiftCutOffMask)); |
| 5598 |
5661 // if (hash == 0) hash = 27; | 5599 // if (hash == 0) hash = 27; |
5662 __ mov(hash, Operand(27), LeaveCC, ne); | 5600 __ mov(hash, Operand(27), LeaveCC, eq); |
5663 } | 5601 } |
5664 | 5602 |
5665 | 5603 |
5666 void SubStringStub::Generate(MacroAssembler* masm) { | 5604 void SubStringStub::Generate(MacroAssembler* masm) { |
5667 Label runtime; | 5605 Label runtime; |
5668 | 5606 |
5669 // Stack frame on entry. | 5607 // Stack frame on entry. |
5670 // lr: return address | 5608 // lr: return address |
5671 // sp[0]: to | 5609 // sp[0]: to |
5672 // sp[4]: from | 5610 // sp[4]: from |
(...skipping 1508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7181 __ bind(&need_incremental); | 7119 __ bind(&need_incremental); |
7182 | 7120 |
7183 // Fall through when we need to inform the incremental marker. | 7121 // Fall through when we need to inform the incremental marker. |
7184 } | 7122 } |
7185 | 7123 |
7186 #undef __ | 7124 #undef __ |
7187 | 7125 |
7188 } } // namespace v8::internal | 7126 } } // namespace v8::internal |
7189 | 7127 |
7190 #endif // V8_TARGET_ARCH_ARM | 7128 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |