| 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 618 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 629 __ b(ne, not_number); | 629 __ b(ne, not_number); |
| 630 __ ConvertToInt32(object, | 630 __ ConvertToInt32(object, |
| 631 dst, | 631 dst, |
| 632 scratch1, | 632 scratch1, |
| 633 scratch2, | 633 scratch2, |
| 634 double_scratch, | 634 double_scratch, |
| 635 ¬_in_int32_range); | 635 ¬_in_int32_range); |
| 636 __ jmp(&done); | 636 __ jmp(&done); |
| 637 | 637 |
| 638 __ bind(¬_in_int32_range); | 638 __ bind(¬_in_int32_range); |
| 639 __ ldr(scratch2, FieldMemOperand(object, HeapNumber::kExponentOffset)); | 639 __ ldr(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset)); |
| 640 __ ldr(scratch1, FieldMemOperand(object, HeapNumber::kMantissaOffset)); | 640 __ ldr(scratch2, FieldMemOperand(object, HeapNumber::kMantissaOffset)); |
| 641 | 641 |
| 642 // Register scratch1 contains mantissa word, scratch2 contains | 642 __ EmitOutOfInt32RangeTruncate(dst, |
| 643 // sign, exponent and mantissa. Extract biased exponent into dst. | 643 scratch1, |
| 644 __ Ubfx(dst, | 644 scratch2, |
| 645 scratch2, | 645 scratch3); |
| 646 HeapNumber::kExponentShift, | |
| 647 HeapNumber::kExponentBits); | |
| 648 | |
| 649 // Express exponent as delta to 31. | |
| 650 __ sub(dst, dst, Operand(HeapNumber::kExponentBias + 31)); | |
| 651 | |
| 652 Label normal_exponent; | |
| 653 // If the delta is larger than kMantissaBits plus one, all bits | |
| 654 // would be shifted away, which means that we can return 0. | |
| 655 __ cmp(dst, Operand(HeapNumber::kMantissaBits + 1)); | |
| 656 __ b(&normal_exponent, lt); | |
| 657 __ mov(dst, Operand(0)); | |
| 658 __ jmp(&done); | |
| 659 | |
| 660 __ bind(&normal_exponent); | |
| 661 const int kShiftBase = HeapNumber::kNonMantissaBitsInTopWord - 1; | |
| 662 // Calculate shift. | |
| 663 __ add(scratch3, dst, Operand(kShiftBase)); | |
| 664 | |
| 665 // Put implicit 1 before the mantissa part in scratch2. | |
| 666 __ orr(scratch2, | |
| 667 scratch2, | |
| 668 Operand(1 << HeapNumber::kMantissaBitsInTopWord)); | |
| 669 | |
| 670 // Save sign. | |
| 671 Register sign = dst; | |
| 672 __ and_(sign, scratch2, Operand(HeapNumber::kSignMask)); | |
| 673 | |
| 674 // Shift mantisssa bits the correct position in high word. | |
| 675 __ mov(scratch2, Operand(scratch2, LSL, scratch3)); | |
| 676 | |
| 677 // Replace the shifted bits with bits from the lower mantissa word. | |
| 678 Label pos_shift, shift_done; | |
| 679 __ rsb(scratch3, scratch3, Operand(32), SetCC); | |
| 680 __ b(&pos_shift, ge); | |
| 681 | |
| 682 // Negate scratch3. | |
| 683 __ rsb(scratch3, scratch3, Operand(0)); | |
| 684 __ mov(scratch1, Operand(scratch1, LSL, scratch3)); | |
| 685 __ jmp(&shift_done); | |
| 686 | |
| 687 __ bind(&pos_shift); | |
| 688 __ mov(scratch1, Operand(scratch1, LSR, scratch3)); | |
| 689 | |
| 690 __ bind(&shift_done); | |
| 691 __ orr(scratch2, scratch2, Operand(scratch1)); | |
| 692 | |
| 693 // Restore sign if necessary. | |
| 694 __ cmp(sign, Operand(0)); | |
| 695 __ rsb(dst, scratch2, Operand(0), LeaveCC, ne); | |
| 696 __ mov(dst, scratch2, LeaveCC, eq); | |
| 697 __ jmp(&done); | 646 __ jmp(&done); |
| 698 | 647 |
| 699 __ bind(&is_smi); | 648 __ bind(&is_smi); |
| 700 __ SmiUntag(dst, object); | 649 __ SmiUntag(dst, object); |
| 701 __ bind(&done); | 650 __ bind(&done); |
| 702 } | 651 } |
| 703 | 652 |
| 704 | 653 |
| 705 void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm, | 654 void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm, |
| 706 Register object, | 655 Register object, |
| (...skipping 4381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5088 __ mov(r3, Operand(r0, ASR, 2), SetCC); | 5037 __ mov(r3, Operand(r0, ASR, 2), SetCC); |
| 5089 __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset), ne); | 5038 __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset), ne); |
| 5090 __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset), eq); | 5039 __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset), eq); |
| 5091 | 5040 |
| 5092 // Check that the irregexp code has been generated for the actual string | 5041 // Check that the irregexp code has been generated for the actual string |
| 5093 // encoding. If it has, the field contains a code object otherwise it contains | 5042 // encoding. If it has, the field contains a code object otherwise it contains |
| 5094 // the hole. | 5043 // the hole. |
| 5095 __ CompareObjectType(r7, r0, r0, CODE_TYPE); | 5044 __ CompareObjectType(r7, r0, r0, CODE_TYPE); |
| 5096 __ b(ne, &runtime); | 5045 __ b(ne, &runtime); |
| 5097 | 5046 |
| 5098 // r3: encoding of subject string (1 if ascii, 0 if two_byte); | 5047 // r3: encoding of subject string (1 if ASCII, 0 if two_byte); |
| 5099 // r7: code | 5048 // r7: code |
| 5100 // subject: Subject string | 5049 // subject: Subject string |
| 5101 // regexp_data: RegExp data (FixedArray) | 5050 // regexp_data: RegExp data (FixedArray) |
| 5102 // Load used arguments before starting to push arguments for call to native | 5051 // Load used arguments before starting to push arguments for call to native |
| 5103 // RegExp code to avoid handling changing stack height. | 5052 // RegExp code to avoid handling changing stack height. |
| 5104 __ ldr(r1, MemOperand(sp, kPreviousIndexOffset)); | 5053 __ ldr(r1, MemOperand(sp, kPreviousIndexOffset)); |
| 5105 __ mov(r1, Operand(r1, ASR, kSmiTagSize)); | 5054 __ mov(r1, Operand(r1, ASR, kSmiTagSize)); |
| 5106 | 5055 |
| 5107 // r1: previous index | 5056 // r1: previous index |
| 5108 // r3: encoding of subject string (1 if ascii, 0 if two_byte); | 5057 // r3: encoding of subject string (1 if ASCII, 0 if two_byte); |
| 5109 // r7: code | 5058 // r7: code |
| 5110 // subject: Subject string | 5059 // subject: Subject string |
| 5111 // regexp_data: RegExp data (FixedArray) | 5060 // regexp_data: RegExp data (FixedArray) |
| 5112 // All checks done. Now push arguments for native regexp code. | 5061 // All checks done. Now push arguments for native regexp code. |
| 5113 __ IncrementCounter(COUNTERS->regexp_entry_native(), 1, r0, r2); | 5062 __ IncrementCounter(COUNTERS->regexp_entry_native(), 1, r0, r2); |
| 5114 | 5063 |
| 5115 // Isolates: note we add an additional parameter here (isolate pointer). | 5064 // Isolates: note we add an additional parameter here (isolate pointer). |
| 5116 static const int kRegExpExecuteArguments = 8; | 5065 static const int kRegExpExecuteArguments = 8; |
| 5117 static const int kParameterRegisters = 4; | 5066 static const int kParameterRegisters = 4; |
| 5118 __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters); | 5067 __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters); |
| (...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5637 // Fast case of Heap::LookupSingleCharacterStringFromCode. | 5586 // Fast case of Heap::LookupSingleCharacterStringFromCode. |
| 5638 STATIC_ASSERT(kSmiTag == 0); | 5587 STATIC_ASSERT(kSmiTag == 0); |
| 5639 STATIC_ASSERT(kSmiShiftSize == 0); | 5588 STATIC_ASSERT(kSmiShiftSize == 0); |
| 5640 ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1)); | 5589 ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1)); |
| 5641 __ tst(code_, | 5590 __ tst(code_, |
| 5642 Operand(kSmiTagMask | | 5591 Operand(kSmiTagMask | |
| 5643 ((~String::kMaxAsciiCharCode) << kSmiTagSize))); | 5592 ((~String::kMaxAsciiCharCode) << kSmiTagSize))); |
| 5644 __ b(ne, &slow_case_); | 5593 __ b(ne, &slow_case_); |
| 5645 | 5594 |
| 5646 __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex); | 5595 __ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex); |
| 5647 // At this point code register contains smi tagged ascii char code. | 5596 // At this point code register contains smi tagged ASCII char code. |
| 5648 STATIC_ASSERT(kSmiTag == 0); | 5597 STATIC_ASSERT(kSmiTag == 0); |
| 5649 __ add(result_, result_, Operand(code_, LSL, kPointerSizeLog2 - kSmiTagSize)); | 5598 __ add(result_, result_, Operand(code_, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 5650 __ ldr(result_, FieldMemOperand(result_, FixedArray::kHeaderSize)); | 5599 __ ldr(result_, FieldMemOperand(result_, FixedArray::kHeaderSize)); |
| 5651 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 5600 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 5652 __ cmp(result_, Operand(ip)); | 5601 __ cmp(result_, Operand(ip)); |
| 5653 __ b(eq, &slow_case_); | 5602 __ b(eq, &slow_case_); |
| 5654 __ bind(&exit_); | 5603 __ bind(&exit_); |
| 5655 } | 5604 } |
| 5656 | 5605 |
| 5657 | 5606 |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5969 __ orr(chars, chars, Operand(c2, LSL, kBitsPerByte)); | 5918 __ orr(chars, chars, Operand(c2, LSL, kBitsPerByte)); |
| 5970 | 5919 |
| 5971 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. | 5920 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. |
| 5972 // hash: hash of two character string. | 5921 // hash: hash of two character string. |
| 5973 | 5922 |
| 5974 // Load symbol table | 5923 // Load symbol table |
| 5975 // Load address of first element of the symbol table. | 5924 // Load address of first element of the symbol table. |
| 5976 Register symbol_table = c2; | 5925 Register symbol_table = c2; |
| 5977 __ LoadRoot(symbol_table, Heap::kSymbolTableRootIndex); | 5926 __ LoadRoot(symbol_table, Heap::kSymbolTableRootIndex); |
| 5978 | 5927 |
| 5979 // Load undefined value | |
| 5980 Register undefined = scratch4; | 5928 Register undefined = scratch4; |
| 5981 __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex); | 5929 __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex); |
| 5982 | 5930 |
| 5983 // Calculate capacity mask from the symbol table capacity. | 5931 // Calculate capacity mask from the symbol table capacity. |
| 5984 Register mask = scratch2; | 5932 Register mask = scratch2; |
| 5985 __ ldr(mask, FieldMemOperand(symbol_table, SymbolTable::kCapacityOffset)); | 5933 __ ldr(mask, FieldMemOperand(symbol_table, SymbolTable::kCapacityOffset)); |
| 5986 __ mov(mask, Operand(mask, ASR, 1)); | 5934 __ mov(mask, Operand(mask, ASR, 1)); |
| 5987 __ sub(mask, mask, Operand(1)); | 5935 __ sub(mask, mask, Operand(1)); |
| 5988 | 5936 |
| 5989 // Calculate untagged address of the first element of the symbol table. | 5937 // Calculate untagged address of the first element of the symbol table. |
| 5990 Register first_symbol_table_element = symbol_table; | 5938 Register first_symbol_table_element = symbol_table; |
| 5991 __ add(first_symbol_table_element, symbol_table, | 5939 __ add(first_symbol_table_element, symbol_table, |
| 5992 Operand(SymbolTable::kElementsStartOffset - kHeapObjectTag)); | 5940 Operand(SymbolTable::kElementsStartOffset - kHeapObjectTag)); |
| 5993 | 5941 |
| 5994 // Registers | 5942 // Registers |
| 5995 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. | 5943 // chars: two character string, char 1 in byte 0 and char 2 in byte 1. |
| 5996 // hash: hash of two character string | 5944 // hash: hash of two character string |
| 5997 // mask: capacity mask | 5945 // mask: capacity mask |
| 5998 // first_symbol_table_element: address of the first element of | 5946 // first_symbol_table_element: address of the first element of |
| 5999 // the symbol table | 5947 // the symbol table |
| 5948 // undefined: the undefined object |
| 6000 // scratch: - | 5949 // scratch: - |
| 6001 | 5950 |
| 6002 // Perform a number of probes in the symbol table. | 5951 // Perform a number of probes in the symbol table. |
| 6003 static const int kProbes = 4; | 5952 static const int kProbes = 4; |
| 6004 Label found_in_symbol_table; | 5953 Label found_in_symbol_table; |
| 6005 Label next_probe[kProbes]; | 5954 Label next_probe[kProbes]; |
| 6006 for (int i = 0; i < kProbes; i++) { | 5955 for (int i = 0; i < kProbes; i++) { |
| 6007 Register candidate = scratch5; // Scratch register contains candidate. | 5956 Register candidate = scratch5; // Scratch register contains candidate. |
| 6008 | 5957 |
| 6009 // Calculate entry in symbol table. | 5958 // Calculate entry in symbol table. |
| 6010 if (i > 0) { | 5959 if (i > 0) { |
| 6011 __ add(candidate, hash, Operand(SymbolTable::GetProbeOffset(i))); | 5960 __ add(candidate, hash, Operand(SymbolTable::GetProbeOffset(i))); |
| 6012 } else { | 5961 } else { |
| 6013 __ mov(candidate, hash); | 5962 __ mov(candidate, hash); |
| 6014 } | 5963 } |
| 6015 | 5964 |
| 6016 __ and_(candidate, candidate, Operand(mask)); | 5965 __ and_(candidate, candidate, Operand(mask)); |
| 6017 | 5966 |
| 6018 // Load the entry from the symble table. | 5967 // Load the entry from the symble table. |
| 6019 STATIC_ASSERT(SymbolTable::kEntrySize == 1); | 5968 STATIC_ASSERT(SymbolTable::kEntrySize == 1); |
| 6020 __ ldr(candidate, | 5969 __ ldr(candidate, |
| 6021 MemOperand(first_symbol_table_element, | 5970 MemOperand(first_symbol_table_element, |
| 6022 candidate, | 5971 candidate, |
| 6023 LSL, | 5972 LSL, |
| 6024 kPointerSizeLog2)); | 5973 kPointerSizeLog2)); |
| 6025 | 5974 |
| 6026 // If entry is undefined no string with this hash can be found. | 5975 // If entry is undefined no string with this hash can be found. |
| 6027 __ cmp(candidate, undefined); | 5976 Label is_string; |
| 5977 __ CompareObjectType(candidate, scratch, scratch, ODDBALL_TYPE); |
| 5978 __ b(ne, &is_string); |
| 5979 |
| 5980 __ cmp(undefined, candidate); |
| 6028 __ b(eq, not_found); | 5981 __ b(eq, not_found); |
| 5982 // Must be null (deleted entry). |
| 5983 if (FLAG_debug_code) { |
| 5984 __ LoadRoot(ip, Heap::kNullValueRootIndex); |
| 5985 __ cmp(ip, candidate); |
| 5986 __ Assert(eq, "oddball in symbol table is not undefined or null"); |
| 5987 } |
| 5988 __ jmp(&next_probe[i]); |
| 5989 |
| 5990 __ bind(&is_string); |
| 5991 |
| 5992 // Check that the candidate is a non-external ASCII string. The instance |
| 5993 // type is still in the scratch register from the CompareObjectType |
| 5994 // operation. |
| 5995 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &next_probe[i]); |
| 6029 | 5996 |
| 6030 // If length is not 2 the string is not a candidate. | 5997 // If length is not 2 the string is not a candidate. |
| 6031 __ ldr(scratch, FieldMemOperand(candidate, String::kLengthOffset)); | 5998 __ ldr(scratch, FieldMemOperand(candidate, String::kLengthOffset)); |
| 6032 __ cmp(scratch, Operand(Smi::FromInt(2))); | 5999 __ cmp(scratch, Operand(Smi::FromInt(2))); |
| 6033 __ b(ne, &next_probe[i]); | 6000 __ b(ne, &next_probe[i]); |
| 6034 | 6001 |
| 6035 // Check that the candidate is a non-external ascii string. | |
| 6036 __ ldr(scratch, FieldMemOperand(candidate, HeapObject::kMapOffset)); | |
| 6037 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | |
| 6038 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, | |
| 6039 &next_probe[i]); | |
| 6040 | |
| 6041 // Check if the two characters match. | 6002 // Check if the two characters match. |
| 6042 // Assumes that word load is little endian. | 6003 // Assumes that word load is little endian. |
| 6043 __ ldrh(scratch, FieldMemOperand(candidate, SeqAsciiString::kHeaderSize)); | 6004 __ ldrh(scratch, FieldMemOperand(candidate, SeqAsciiString::kHeaderSize)); |
| 6044 __ cmp(chars, scratch); | 6005 __ cmp(chars, scratch); |
| 6045 __ b(eq, &found_in_symbol_table); | 6006 __ b(eq, &found_in_symbol_table); |
| 6046 __ bind(&next_probe[i]); | 6007 __ bind(&next_probe[i]); |
| 6047 } | 6008 } |
| 6048 | 6009 |
| 6049 // No matching 2 character string found by probing. | 6010 // No matching 2 character string found by probing. |
| 6050 __ jmp(not_found); | 6011 __ jmp(not_found); |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6186 __ ldr(r4, FieldMemOperand(r5, String::kLengthOffset)); | 6147 __ ldr(r4, FieldMemOperand(r5, String::kLengthOffset)); |
| 6187 __ cmp(r4, Operand(to)); | 6148 __ cmp(r4, Operand(to)); |
| 6188 __ b(lt, &runtime); // Fail if to > length. | 6149 __ b(lt, &runtime); // Fail if to > length. |
| 6189 to = no_reg; | 6150 to = no_reg; |
| 6190 | 6151 |
| 6191 // r1: instance type. | 6152 // r1: instance type. |
| 6192 // r2: result string length. | 6153 // r2: result string length. |
| 6193 // r3: from index (untaged smi) | 6154 // r3: from index (untaged smi) |
| 6194 // r5: string. | 6155 // r5: string. |
| 6195 // r7 (a.k.a. from): from offset (smi) | 6156 // r7 (a.k.a. from): from offset (smi) |
| 6196 // Check for flat ascii string. | 6157 // Check for flat ASCII string. |
| 6197 Label non_ascii_flat; | 6158 Label non_ascii_flat; |
| 6198 __ tst(r1, Operand(kStringEncodingMask)); | 6159 __ tst(r1, Operand(kStringEncodingMask)); |
| 6199 STATIC_ASSERT(kTwoByteStringTag == 0); | 6160 STATIC_ASSERT(kTwoByteStringTag == 0); |
| 6200 __ b(eq, &non_ascii_flat); | 6161 __ b(eq, &non_ascii_flat); |
| 6201 | 6162 |
| 6202 Label result_longer_than_two; | 6163 Label result_longer_than_two; |
| 6203 __ cmp(r2, Operand(2)); | 6164 __ cmp(r2, Operand(2)); |
| 6204 __ b(gt, &result_longer_than_two); | 6165 __ b(gt, &result_longer_than_two); |
| 6205 | 6166 |
| 6206 // Sub string of length 2 requested. | 6167 // Sub string of length 2 requested. |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6362 __ b(ne, ¬_same); | 6323 __ b(ne, ¬_same); |
| 6363 STATIC_ASSERT(EQUAL == 0); | 6324 STATIC_ASSERT(EQUAL == 0); |
| 6364 STATIC_ASSERT(kSmiTag == 0); | 6325 STATIC_ASSERT(kSmiTag == 0); |
| 6365 __ mov(r0, Operand(Smi::FromInt(EQUAL))); | 6326 __ mov(r0, Operand(Smi::FromInt(EQUAL))); |
| 6366 __ IncrementCounter(COUNTERS->string_compare_native(), 1, r1, r2); | 6327 __ IncrementCounter(COUNTERS->string_compare_native(), 1, r1, r2); |
| 6367 __ add(sp, sp, Operand(2 * kPointerSize)); | 6328 __ add(sp, sp, Operand(2 * kPointerSize)); |
| 6368 __ Ret(); | 6329 __ Ret(); |
| 6369 | 6330 |
| 6370 __ bind(¬_same); | 6331 __ bind(¬_same); |
| 6371 | 6332 |
| 6372 // Check that both objects are sequential ascii strings. | 6333 // Check that both objects are sequential ASCII strings. |
| 6373 __ JumpIfNotBothSequentialAsciiStrings(r1, r0, r2, r3, &runtime); | 6334 __ JumpIfNotBothSequentialAsciiStrings(r1, r0, r2, r3, &runtime); |
| 6374 | 6335 |
| 6375 // Compare flat ascii strings natively. Remove arguments from stack first. | 6336 // Compare flat ASCII strings natively. Remove arguments from stack first. |
| 6376 __ IncrementCounter(COUNTERS->string_compare_native(), 1, r2, r3); | 6337 __ IncrementCounter(COUNTERS->string_compare_native(), 1, r2, r3); |
| 6377 __ add(sp, sp, Operand(2 * kPointerSize)); | 6338 __ add(sp, sp, Operand(2 * kPointerSize)); |
| 6378 GenerateCompareFlatAsciiStrings(masm, r1, r0, r2, r3, r4, r5); | 6339 GenerateCompareFlatAsciiStrings(masm, r1, r0, r2, r3, r4, r5); |
| 6379 | 6340 |
| 6380 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 6341 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
| 6381 // tagged as a small integer. | 6342 // tagged as a small integer. |
| 6382 __ bind(&runtime); | 6343 __ bind(&runtime); |
| 6383 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 6344 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
| 6384 } | 6345 } |
| 6385 | 6346 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6457 // r1: second string | 6418 // r1: second string |
| 6458 // r2: length of first string | 6419 // r2: length of first string |
| 6459 // r3: length of second string | 6420 // r3: length of second string |
| 6460 // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) | 6421 // r4: first string instance type (if flags_ == NO_STRING_ADD_FLAGS) |
| 6461 // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) | 6422 // r5: second string instance type (if flags_ == NO_STRING_ADD_FLAGS) |
| 6462 // Look at the length of the result of adding the two strings. | 6423 // Look at the length of the result of adding the two strings. |
| 6463 Label string_add_flat_result, longer_than_two; | 6424 Label string_add_flat_result, longer_than_two; |
| 6464 // Adding two lengths can't overflow. | 6425 // Adding two lengths can't overflow. |
| 6465 STATIC_ASSERT(String::kMaxLength < String::kMaxLength * 2); | 6426 STATIC_ASSERT(String::kMaxLength < String::kMaxLength * 2); |
| 6466 __ add(r6, r2, Operand(r3)); | 6427 __ add(r6, r2, Operand(r3)); |
| 6467 // Use the runtime system when adding two one character strings, as it | 6428 // Use the symbol table when adding two one character strings, as it |
| 6468 // contains optimizations for this specific case using the symbol table. | 6429 // helps later optimizations to return a symbol here. |
| 6469 __ cmp(r6, Operand(2)); | 6430 __ cmp(r6, Operand(2)); |
| 6470 __ b(ne, &longer_than_two); | 6431 __ b(ne, &longer_than_two); |
| 6471 | 6432 |
| 6472 // Check that both strings are non-external ascii strings. | 6433 // Check that both strings are non-external ASCII strings. |
| 6473 if (flags_ != NO_STRING_ADD_FLAGS) { | 6434 if (flags_ != NO_STRING_ADD_FLAGS) { |
| 6474 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); | 6435 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 6475 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); | 6436 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 6476 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); | 6437 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); |
| 6477 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); | 6438 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); |
| 6478 } | 6439 } |
| 6479 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r7, | 6440 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r7, |
| 6480 &string_add_runtime); | 6441 &string_add_runtime); |
| 6481 | 6442 |
| 6482 // Get the two characters forming the sub string. | 6443 // Get the two characters forming the sub string. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 6510 __ cmp(r6, Operand(String::kMinNonFlatLength)); | 6471 __ cmp(r6, Operand(String::kMinNonFlatLength)); |
| 6511 __ b(lt, &string_add_flat_result); | 6472 __ b(lt, &string_add_flat_result); |
| 6512 // Handle exceptionally long strings in the runtime system. | 6473 // Handle exceptionally long strings in the runtime system. |
| 6513 STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0); | 6474 STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0); |
| 6514 ASSERT(IsPowerOf2(String::kMaxLength + 1)); | 6475 ASSERT(IsPowerOf2(String::kMaxLength + 1)); |
| 6515 // kMaxLength + 1 is representable as shifted literal, kMaxLength is not. | 6476 // kMaxLength + 1 is representable as shifted literal, kMaxLength is not. |
| 6516 __ cmp(r6, Operand(String::kMaxLength + 1)); | 6477 __ cmp(r6, Operand(String::kMaxLength + 1)); |
| 6517 __ b(hs, &string_add_runtime); | 6478 __ b(hs, &string_add_runtime); |
| 6518 | 6479 |
| 6519 // If result is not supposed to be flat, allocate a cons string object. | 6480 // If result is not supposed to be flat, allocate a cons string object. |
| 6520 // If both strings are ascii the result is an ascii cons string. | 6481 // If both strings are ASCII the result is an ASCII cons string. |
| 6521 if (flags_ != NO_STRING_ADD_FLAGS) { | 6482 if (flags_ != NO_STRING_ADD_FLAGS) { |
| 6522 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); | 6483 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 6523 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); | 6484 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 6524 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); | 6485 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); |
| 6525 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); | 6486 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset)); |
| 6526 } | 6487 } |
| 6527 Label non_ascii, allocated, ascii_data; | 6488 Label non_ascii, allocated, ascii_data; |
| 6528 STATIC_ASSERT(kTwoByteStringTag == 0); | 6489 STATIC_ASSERT(kTwoByteStringTag == 0); |
| 6529 __ tst(r4, Operand(kStringEncodingMask)); | 6490 __ tst(r4, Operand(kStringEncodingMask)); |
| 6530 __ tst(r5, Operand(kStringEncodingMask), ne); | 6491 __ tst(r5, Operand(kStringEncodingMask), ne); |
| 6531 __ b(eq, &non_ascii); | 6492 __ b(eq, &non_ascii); |
| 6532 | 6493 |
| 6533 // Allocate an ASCII cons string. | 6494 // Allocate an ASCII cons string. |
| 6534 __ bind(&ascii_data); | 6495 __ bind(&ascii_data); |
| 6535 __ AllocateAsciiConsString(r7, r6, r4, r5, &string_add_runtime); | 6496 __ AllocateAsciiConsString(r7, r6, r4, r5, &string_add_runtime); |
| 6536 __ bind(&allocated); | 6497 __ bind(&allocated); |
| 6537 // Fill the fields of the cons string. | 6498 // Fill the fields of the cons string. |
| 6538 __ str(r0, FieldMemOperand(r7, ConsString::kFirstOffset)); | 6499 __ str(r0, FieldMemOperand(r7, ConsString::kFirstOffset)); |
| 6539 __ str(r1, FieldMemOperand(r7, ConsString::kSecondOffset)); | 6500 __ str(r1, FieldMemOperand(r7, ConsString::kSecondOffset)); |
| 6540 __ mov(r0, Operand(r7)); | 6501 __ mov(r0, Operand(r7)); |
| 6541 __ IncrementCounter(COUNTERS->string_add_native(), 1, r2, r3); | 6502 __ IncrementCounter(COUNTERS->string_add_native(), 1, r2, r3); |
| 6542 __ add(sp, sp, Operand(2 * kPointerSize)); | 6503 __ add(sp, sp, Operand(2 * kPointerSize)); |
| 6543 __ Ret(); | 6504 __ Ret(); |
| 6544 | 6505 |
| 6545 __ bind(&non_ascii); | 6506 __ bind(&non_ascii); |
| 6546 // At least one of the strings is two-byte. Check whether it happens | 6507 // At least one of the strings is two-byte. Check whether it happens |
| 6547 // to contain only ascii characters. | 6508 // to contain only ASCII characters. |
| 6548 // r4: first instance type. | 6509 // r4: first instance type. |
| 6549 // r5: second instance type. | 6510 // r5: second instance type. |
| 6550 __ tst(r4, Operand(kAsciiDataHintMask)); | 6511 __ tst(r4, Operand(kAsciiDataHintMask)); |
| 6551 __ tst(r5, Operand(kAsciiDataHintMask), ne); | 6512 __ tst(r5, Operand(kAsciiDataHintMask), ne); |
| 6552 __ b(ne, &ascii_data); | 6513 __ b(ne, &ascii_data); |
| 6553 __ eor(r4, r4, Operand(r5)); | 6514 __ eor(r4, r4, Operand(r5)); |
| 6554 STATIC_ASSERT(kAsciiStringTag != 0 && kAsciiDataHintTag != 0); | 6515 STATIC_ASSERT(kAsciiStringTag != 0 && kAsciiDataHintTag != 0); |
| 6555 __ and_(r4, r4, Operand(kAsciiStringTag | kAsciiDataHintTag)); | 6516 __ and_(r4, r4, Operand(kAsciiStringTag | kAsciiDataHintTag)); |
| 6556 __ cmp(r4, Operand(kAsciiStringTag | kAsciiDataHintTag)); | 6517 __ cmp(r4, Operand(kAsciiStringTag | kAsciiDataHintTag)); |
| 6557 __ b(eq, &ascii_data); | 6518 __ b(eq, &ascii_data); |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6718 __ cmp(scratch2, | 6679 __ cmp(scratch2, |
| 6719 Operand(1 << Map::kStringWrapperSafeForDefaultValueOf)); | 6680 Operand(1 << Map::kStringWrapperSafeForDefaultValueOf)); |
| 6720 __ b(ne, slow); | 6681 __ b(ne, slow); |
| 6721 __ ldr(arg, FieldMemOperand(arg, JSValue::kValueOffset)); | 6682 __ ldr(arg, FieldMemOperand(arg, JSValue::kValueOffset)); |
| 6722 __ str(arg, MemOperand(sp, stack_offset)); | 6683 __ str(arg, MemOperand(sp, stack_offset)); |
| 6723 | 6684 |
| 6724 __ bind(&done); | 6685 __ bind(&done); |
| 6725 } | 6686 } |
| 6726 | 6687 |
| 6727 | 6688 |
| 6728 void StringCharAtStub::Generate(MacroAssembler* masm) { | |
| 6729 // Expects two arguments (object, index) on the stack: | |
| 6730 // lr: return address | |
| 6731 // sp[0]: index | |
| 6732 // sp[4]: object | |
| 6733 Register object = r1; | |
| 6734 Register index = r0; | |
| 6735 Register scratch1 = r2; | |
| 6736 Register scratch2 = r3; | |
| 6737 Register result = r0; | |
| 6738 | |
| 6739 // Get object and index from the stack. | |
| 6740 __ pop(index); | |
| 6741 __ pop(object); | |
| 6742 | |
| 6743 Label need_conversion; | |
| 6744 Label index_out_of_range; | |
| 6745 Label done; | |
| 6746 StringCharAtGenerator generator(object, | |
| 6747 index, | |
| 6748 scratch1, | |
| 6749 scratch2, | |
| 6750 result, | |
| 6751 &need_conversion, | |
| 6752 &need_conversion, | |
| 6753 &index_out_of_range, | |
| 6754 STRING_INDEX_IS_NUMBER); | |
| 6755 generator.GenerateFast(masm); | |
| 6756 __ b(&done); | |
| 6757 | |
| 6758 __ bind(&index_out_of_range); | |
| 6759 // When the index is out of range, the spec requires us to return | |
| 6760 // the empty string. | |
| 6761 __ LoadRoot(result, Heap::kEmptyStringRootIndex); | |
| 6762 __ jmp(&done); | |
| 6763 | |
| 6764 __ bind(&need_conversion); | |
| 6765 // Move smi zero into the result register, which will trigger | |
| 6766 // conversion. | |
| 6767 __ mov(result, Operand(Smi::FromInt(0))); | |
| 6768 __ b(&done); | |
| 6769 | |
| 6770 StubRuntimeCallHelper call_helper; | |
| 6771 generator.GenerateSlow(masm, call_helper); | |
| 6772 | |
| 6773 __ bind(&done); | |
| 6774 __ Ret(); | |
| 6775 } | |
| 6776 | |
| 6777 | |
| 6778 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { | 6689 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { |
| 6779 ASSERT(state_ == CompareIC::SMIS); | 6690 ASSERT(state_ == CompareIC::SMIS); |
| 6780 Label miss; | 6691 Label miss; |
| 6781 __ orr(r2, r1, r0); | 6692 __ orr(r2, r1, r0); |
| 6782 __ tst(r2, Operand(kSmiTagMask)); | 6693 __ tst(r2, Operand(kSmiTagMask)); |
| 6783 __ b(ne, &miss); | 6694 __ b(ne, &miss); |
| 6784 | 6695 |
| 6785 if (GetCondition() == eq) { | 6696 if (GetCondition() == eq) { |
| 6786 // For equality we do not care about the sign of the result. | 6697 // For equality we do not care about the sign of the result. |
| 6787 __ sub(r0, r0, r1, SetCC); | 6698 __ sub(r0, r0, r1, SetCC); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6914 __ str(pc, MemOperand(sp, 0)); | 6825 __ str(pc, MemOperand(sp, 0)); |
| 6915 __ Jump(target); // Call the C++ function. | 6826 __ Jump(target); // Call the C++ function. |
| 6916 } | 6827 } |
| 6917 | 6828 |
| 6918 | 6829 |
| 6919 #undef __ | 6830 #undef __ |
| 6920 | 6831 |
| 6921 } } // namespace v8::internal | 6832 } } // namespace v8::internal |
| 6922 | 6833 |
| 6923 #endif // V8_TARGET_ARCH_ARM | 6834 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |