| 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 |