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 1440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1451 // contains two elements (number and string) for each cache entry. | 1451 // contains two elements (number and string) for each cache entry. |
1452 __ ldr(mask, FieldMemOperand(number_string_cache, FixedArray::kLengthOffset)); | 1452 __ ldr(mask, FieldMemOperand(number_string_cache, FixedArray::kLengthOffset)); |
1453 // Divide length by two (length is a smi). | 1453 // Divide length by two (length is a smi). |
1454 __ mov(mask, Operand(mask, ASR, kSmiTagSize + 1)); | 1454 __ mov(mask, Operand(mask, ASR, kSmiTagSize + 1)); |
1455 __ sub(mask, mask, Operand(1)); // Make mask. | 1455 __ sub(mask, mask, Operand(1)); // Make mask. |
1456 | 1456 |
1457 // Calculate the entry in the number string cache. The hash value in the | 1457 // Calculate the entry in the number string cache. The hash value in the |
1458 // number string cache for smis is just the smi value, and the hash for | 1458 // number string cache for smis is just the smi value, and the hash for |
1459 // doubles is the xor of the upper and lower words. See | 1459 // doubles is the xor of the upper and lower words. See |
1460 // Heap::GetNumberStringCache. | 1460 // Heap::GetNumberStringCache. |
| 1461 Isolate* isolate = masm->isolate(); |
1461 Label is_smi; | 1462 Label is_smi; |
1462 Label load_result_from_cache; | 1463 Label load_result_from_cache; |
1463 if (!object_is_smi) { | 1464 if (!object_is_smi) { |
1464 __ JumpIfSmi(object, &is_smi); | 1465 __ JumpIfSmi(object, &is_smi); |
1465 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { | 1466 if (isolate->cpu_features()->IsSupported(VFP3)) { |
1466 CpuFeatures::Scope scope(VFP3); | 1467 CpuFeatures::Scope scope(VFP3); |
1467 __ CheckMap(object, | 1468 __ CheckMap(object, |
1468 scratch1, | 1469 scratch1, |
1469 Heap::kHeapNumberMapRootIndex, | 1470 Heap::kHeapNumberMapRootIndex, |
1470 not_found, | 1471 not_found, |
1471 true); | 1472 true); |
1472 | 1473 |
1473 STATIC_ASSERT(8 == kDoubleSize); | 1474 STATIC_ASSERT(8 == kDoubleSize); |
1474 __ add(scratch1, | 1475 __ add(scratch1, |
1475 object, | 1476 object, |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1512 // Check if the entry is the smi we are looking for. | 1513 // Check if the entry is the smi we are looking for. |
1513 Register probe = mask; | 1514 Register probe = mask; |
1514 __ ldr(probe, FieldMemOperand(scratch, FixedArray::kHeaderSize)); | 1515 __ ldr(probe, FieldMemOperand(scratch, FixedArray::kHeaderSize)); |
1515 __ cmp(object, probe); | 1516 __ cmp(object, probe); |
1516 __ b(ne, not_found); | 1517 __ b(ne, not_found); |
1517 | 1518 |
1518 // Get the result from the cache. | 1519 // Get the result from the cache. |
1519 __ bind(&load_result_from_cache); | 1520 __ bind(&load_result_from_cache); |
1520 __ ldr(result, | 1521 __ ldr(result, |
1521 FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize)); | 1522 FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize)); |
1522 __ IncrementCounter(COUNTERS->number_to_string_native(), | 1523 __ IncrementCounter(isolate->counters()->number_to_string_native(), |
1523 1, | 1524 1, |
1524 scratch1, | 1525 scratch1, |
1525 scratch2); | 1526 scratch2); |
1526 } | 1527 } |
1527 | 1528 |
1528 | 1529 |
1529 void NumberToStringStub::Generate(MacroAssembler* masm) { | 1530 void NumberToStringStub::Generate(MacroAssembler* masm) { |
1530 Label runtime; | 1531 Label runtime; |
1531 | 1532 |
1532 __ ldr(r1, MemOperand(sp, 0)); | 1533 __ ldr(r1, MemOperand(sp, 0)); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1588 // 4) Jump to lhs_not_nan. | 1589 // 4) Jump to lhs_not_nan. |
1589 // In cases 3 and 4 we have found out we were dealing with a number-number | 1590 // In cases 3 and 4 we have found out we were dealing with a number-number |
1590 // comparison. If VFP3 is supported the double values of the numbers have | 1591 // comparison. If VFP3 is supported the double values of the numbers have |
1591 // been loaded into d7 and d6. Otherwise, the double values have been loaded | 1592 // been loaded into d7 and d6. Otherwise, the double values have been loaded |
1592 // into r0, r1, r2, and r3. | 1593 // into r0, r1, r2, and r3. |
1593 EmitSmiNonsmiComparison(masm, lhs_, rhs_, &lhs_not_nan, &slow, strict_); | 1594 EmitSmiNonsmiComparison(masm, lhs_, rhs_, &lhs_not_nan, &slow, strict_); |
1594 | 1595 |
1595 __ bind(&both_loaded_as_doubles); | 1596 __ bind(&both_loaded_as_doubles); |
1596 // The arguments have been converted to doubles and stored in d6 and d7, if | 1597 // The arguments have been converted to doubles and stored in d6 and d7, if |
1597 // VFP3 is supported, or in r0, r1, r2, and r3. | 1598 // VFP3 is supported, or in r0, r1, r2, and r3. |
1598 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { | 1599 Isolate* isolate = masm->isolate(); |
| 1600 if (isolate->cpu_features()->IsSupported(VFP3)) { |
1599 __ bind(&lhs_not_nan); | 1601 __ bind(&lhs_not_nan); |
1600 CpuFeatures::Scope scope(VFP3); | 1602 CpuFeatures::Scope scope(VFP3); |
1601 Label no_nan; | 1603 Label no_nan; |
1602 // ARMv7 VFP3 instructions to implement double precision comparison. | 1604 // ARMv7 VFP3 instructions to implement double precision comparison. |
1603 __ VFPCompareAndSetFlags(d7, d6); | 1605 __ VFPCompareAndSetFlags(d7, d6); |
1604 Label nan; | 1606 Label nan; |
1605 __ b(vs, &nan); | 1607 __ b(vs, &nan); |
1606 __ mov(r0, Operand(EQUAL), LeaveCC, eq); | 1608 __ mov(r0, Operand(EQUAL), LeaveCC, eq); |
1607 __ mov(r0, Operand(LESS), LeaveCC, lt); | 1609 __ mov(r0, Operand(LESS), LeaveCC, lt); |
1608 __ mov(r0, Operand(GREATER), LeaveCC, gt); | 1610 __ mov(r0, Operand(GREATER), LeaveCC, gt); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1658 // Assumes that r2 is the type of rhs_ on entry. | 1660 // Assumes that r2 is the type of rhs_ on entry. |
1659 EmitCheckForSymbolsOrObjects(masm, lhs_, rhs_, &flat_string_check, &slow); | 1661 EmitCheckForSymbolsOrObjects(masm, lhs_, rhs_, &flat_string_check, &slow); |
1660 } | 1662 } |
1661 | 1663 |
1662 // Check for both being sequential ASCII strings, and inline if that is the | 1664 // Check for both being sequential ASCII strings, and inline if that is the |
1663 // case. | 1665 // case. |
1664 __ bind(&flat_string_check); | 1666 __ bind(&flat_string_check); |
1665 | 1667 |
1666 __ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs_, rhs_, r2, r3, &slow); | 1668 __ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs_, rhs_, r2, r3, &slow); |
1667 | 1669 |
1668 __ IncrementCounter(COUNTERS->string_compare_native(), 1, r2, r3); | 1670 __ IncrementCounter(isolate->counters()->string_compare_native(), 1, r2, r3); |
1669 StringCompareStub::GenerateCompareFlatAsciiStrings(masm, | 1671 StringCompareStub::GenerateCompareFlatAsciiStrings(masm, |
1670 lhs_, | 1672 lhs_, |
1671 rhs_, | 1673 rhs_, |
1672 r2, | 1674 r2, |
1673 r3, | 1675 r3, |
1674 r4, | 1676 r4, |
1675 r5); | 1677 r5); |
1676 // Never falls through to here. | 1678 // Never falls through to here. |
1677 | 1679 |
1678 __ bind(&slow); | 1680 __ bind(&slow); |
(...skipping 3403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5082 // RegExp code to avoid handling changing stack height. | 5084 // RegExp code to avoid handling changing stack height. |
5083 __ ldr(r1, MemOperand(sp, kPreviousIndexOffset)); | 5085 __ ldr(r1, MemOperand(sp, kPreviousIndexOffset)); |
5084 __ mov(r1, Operand(r1, ASR, kSmiTagSize)); | 5086 __ mov(r1, Operand(r1, ASR, kSmiTagSize)); |
5085 | 5087 |
5086 // r1: previous index | 5088 // r1: previous index |
5087 // r3: encoding of subject string (1 if ASCII, 0 if two_byte); | 5089 // r3: encoding of subject string (1 if ASCII, 0 if two_byte); |
5088 // r7: code | 5090 // r7: code |
5089 // subject: Subject string | 5091 // subject: Subject string |
5090 // regexp_data: RegExp data (FixedArray) | 5092 // regexp_data: RegExp data (FixedArray) |
5091 // All checks done. Now push arguments for native regexp code. | 5093 // All checks done. Now push arguments for native regexp code. |
5092 __ IncrementCounter(COUNTERS->regexp_entry_native(), 1, r0, r2); | 5094 __ IncrementCounter(isolate->counters()->regexp_entry_native(), 1, r0, r2); |
5093 | 5095 |
5094 // Isolates: note we add an additional parameter here (isolate pointer). | 5096 // Isolates: note we add an additional parameter here (isolate pointer). |
5095 static const int kRegExpExecuteArguments = 8; | 5097 static const int kRegExpExecuteArguments = 8; |
5096 static const int kParameterRegisters = 4; | 5098 static const int kParameterRegisters = 4; |
5097 __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters); | 5099 __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters); |
5098 | 5100 |
5099 // Stack pointer now points to cell where return address is to be written. | 5101 // Stack pointer now points to cell where return address is to be written. |
5100 // Arguments are before that on the stack or in registers. | 5102 // Arguments are before that on the stack or in registers. |
5101 | 5103 |
5102 // Argument 8 (sp[16]): Pass current isolate address. | 5104 // Argument 8 (sp[16]): Pass current isolate address. |
(...skipping 995 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6098 // nothing can be assumed about the arguments. It is tested that: | 6100 // nothing can be assumed about the arguments. It is tested that: |
6099 // "string" is a sequential string, | 6101 // "string" is a sequential string, |
6100 // both "from" and "to" are smis, and | 6102 // both "from" and "to" are smis, and |
6101 // 0 <= from <= to <= string.length. | 6103 // 0 <= from <= to <= string.length. |
6102 // If any of these assumptions fail, we call the runtime system. | 6104 // If any of these assumptions fail, we call the runtime system. |
6103 | 6105 |
6104 static const int kToOffset = 0 * kPointerSize; | 6106 static const int kToOffset = 0 * kPointerSize; |
6105 static const int kFromOffset = 1 * kPointerSize; | 6107 static const int kFromOffset = 1 * kPointerSize; |
6106 static const int kStringOffset = 2 * kPointerSize; | 6108 static const int kStringOffset = 2 * kPointerSize; |
6107 | 6109 |
6108 | |
6109 // Check bounds and smi-ness. | 6110 // Check bounds and smi-ness. |
6110 Register to = r6; | 6111 Register to = r6; |
6111 Register from = r7; | 6112 Register from = r7; |
6112 __ Ldrd(to, from, MemOperand(sp, kToOffset)); | 6113 __ Ldrd(to, from, MemOperand(sp, kToOffset)); |
6113 STATIC_ASSERT(kFromOffset == kToOffset + 4); | 6114 STATIC_ASSERT(kFromOffset == kToOffset + 4); |
6114 STATIC_ASSERT(kSmiTag == 0); | 6115 STATIC_ASSERT(kSmiTag == 0); |
6115 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); | 6116 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); |
6116 // I.e., arithmetic shift right by one un-smi-tags. | 6117 // I.e., arithmetic shift right by one un-smi-tags. |
6117 __ mov(r2, Operand(to, ASR, 1), SetCC); | 6118 __ mov(r2, Operand(to, ASR, 1), SetCC); |
6118 __ mov(r3, Operand(from, ASR, 1), SetCC, cc); | 6119 __ mov(r3, Operand(from, ASR, 1), SetCC, cc); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6199 // Sub string of length 2 requested. | 6200 // Sub string of length 2 requested. |
6200 // Get the two characters forming the sub string. | 6201 // Get the two characters forming the sub string. |
6201 __ add(r5, r5, Operand(r3)); | 6202 __ add(r5, r5, Operand(r3)); |
6202 __ ldrb(r3, FieldMemOperand(r5, SeqAsciiString::kHeaderSize)); | 6203 __ ldrb(r3, FieldMemOperand(r5, SeqAsciiString::kHeaderSize)); |
6203 __ ldrb(r4, FieldMemOperand(r5, SeqAsciiString::kHeaderSize + 1)); | 6204 __ ldrb(r4, FieldMemOperand(r5, SeqAsciiString::kHeaderSize + 1)); |
6204 | 6205 |
6205 // Try to lookup two character string in symbol table. | 6206 // Try to lookup two character string in symbol table. |
6206 Label make_two_character_string; | 6207 Label make_two_character_string; |
6207 StringHelper::GenerateTwoCharacterSymbolTableProbe( | 6208 StringHelper::GenerateTwoCharacterSymbolTableProbe( |
6208 masm, r3, r4, r1, r5, r6, r7, r9, &make_two_character_string); | 6209 masm, r3, r4, r1, r5, r6, r7, r9, &make_two_character_string); |
6209 __ IncrementCounter(COUNTERS->sub_string_native(), 1, r3, r4); | 6210 Counters* counters = masm->isolate()->counters(); |
| 6211 __ IncrementCounter(counters->sub_string_native(), 1, r3, r4); |
6210 __ add(sp, sp, Operand(3 * kPointerSize)); | 6212 __ add(sp, sp, Operand(3 * kPointerSize)); |
6211 __ Ret(); | 6213 __ Ret(); |
6212 | 6214 |
6213 // r2: result string length. | 6215 // r2: result string length. |
6214 // r3: two characters combined into halfword in little endian byte order. | 6216 // r3: two characters combined into halfword in little endian byte order. |
6215 __ bind(&make_two_character_string); | 6217 __ bind(&make_two_character_string); |
6216 __ AllocateAsciiString(r0, r2, r4, r5, r9, &runtime); | 6218 __ AllocateAsciiString(r0, r2, r4, r5, r9, &runtime); |
6217 __ strh(r3, FieldMemOperand(r0, SeqAsciiString::kHeaderSize)); | 6219 __ strh(r3, FieldMemOperand(r0, SeqAsciiString::kHeaderSize)); |
6218 __ IncrementCounter(COUNTERS->sub_string_native(), 1, r3, r4); | 6220 __ IncrementCounter(counters->sub_string_native(), 1, r3, r4); |
6219 __ add(sp, sp, Operand(3 * kPointerSize)); | 6221 __ add(sp, sp, Operand(3 * kPointerSize)); |
6220 __ Ret(); | 6222 __ Ret(); |
6221 | 6223 |
6222 __ bind(&result_longer_than_two); | 6224 __ bind(&result_longer_than_two); |
6223 | 6225 |
6224 // Allocate the result. | 6226 // Allocate the result. |
6225 __ AllocateAsciiString(r0, r2, r3, r4, r1, &runtime); | 6227 __ AllocateAsciiString(r0, r2, r3, r4, r1, &runtime); |
6226 | 6228 |
6227 // r0: result string. | 6229 // r0: result string. |
6228 // r2: result string length. | 6230 // r2: result string length. |
6229 // r5: string. | 6231 // r5: string. |
6230 // r7 (a.k.a. from): from offset (smi) | 6232 // r7 (a.k.a. from): from offset (smi) |
6231 // Locate first character of result. | 6233 // Locate first character of result. |
6232 __ add(r1, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 6234 __ add(r1, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
6233 // Locate 'from' character of string. | 6235 // Locate 'from' character of string. |
6234 __ add(r5, r5, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 6236 __ add(r5, r5, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
6235 __ add(r5, r5, Operand(from, ASR, 1)); | 6237 __ add(r5, r5, Operand(from, ASR, 1)); |
6236 | 6238 |
6237 // r0: result string. | 6239 // r0: result string. |
6238 // r1: first character of result string. | 6240 // r1: first character of result string. |
6239 // r2: result string length. | 6241 // r2: result string length. |
6240 // r5: first character of sub string to copy. | 6242 // r5: first character of sub string to copy. |
6241 STATIC_ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0); | 6243 STATIC_ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0); |
6242 StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9, | 6244 StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9, |
6243 COPY_ASCII | DEST_ALWAYS_ALIGNED); | 6245 COPY_ASCII | DEST_ALWAYS_ALIGNED); |
6244 __ IncrementCounter(COUNTERS->sub_string_native(), 1, r3, r4); | 6246 __ IncrementCounter(counters->sub_string_native(), 1, r3, r4); |
6245 __ add(sp, sp, Operand(3 * kPointerSize)); | 6247 __ add(sp, sp, Operand(3 * kPointerSize)); |
6246 __ Ret(); | 6248 __ Ret(); |
6247 | 6249 |
6248 __ bind(&non_ascii_flat); | 6250 __ bind(&non_ascii_flat); |
6249 // r2: result string length. | 6251 // r2: result string length. |
6250 // r5: string. | 6252 // r5: string. |
6251 // r7 (a.k.a. from): from offset (smi) | 6253 // r7 (a.k.a. from): from offset (smi) |
6252 // Check for flat two byte string. | 6254 // Check for flat two byte string. |
6253 | 6255 |
6254 // Allocate the result. | 6256 // Allocate the result. |
(...skipping 11 matching lines...) Expand all Loading... |
6266 __ add(r5, r5, Operand(from)); | 6268 __ add(r5, r5, Operand(from)); |
6267 from = no_reg; | 6269 from = no_reg; |
6268 | 6270 |
6269 // r0: result string. | 6271 // r0: result string. |
6270 // r1: first character of result. | 6272 // r1: first character of result. |
6271 // r2: result length. | 6273 // r2: result length. |
6272 // r5: first character of string to copy. | 6274 // r5: first character of string to copy. |
6273 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); | 6275 STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); |
6274 StringHelper::GenerateCopyCharactersLong( | 6276 StringHelper::GenerateCopyCharactersLong( |
6275 masm, r1, r5, r2, r3, r4, r6, r7, r9, DEST_ALWAYS_ALIGNED); | 6277 masm, r1, r5, r2, r3, r4, r6, r7, r9, DEST_ALWAYS_ALIGNED); |
6276 __ IncrementCounter(COUNTERS->sub_string_native(), 1, r3, r4); | 6278 __ IncrementCounter(counters->sub_string_native(), 1, r3, r4); |
6277 __ add(sp, sp, Operand(3 * kPointerSize)); | 6279 __ add(sp, sp, Operand(3 * kPointerSize)); |
6278 __ Ret(); | 6280 __ Ret(); |
6279 | 6281 |
6280 // Just jump to runtime to create the sub string. | 6282 // Just jump to runtime to create the sub string. |
6281 __ bind(&runtime); | 6283 __ bind(&runtime); |
6282 __ TailCallRuntime(Runtime::kSubString, 3, 1); | 6284 __ TailCallRuntime(Runtime::kSubString, 3, 1); |
6283 } | 6285 } |
6284 | 6286 |
6285 | 6287 |
6286 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, | 6288 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6338 // Fall through to here if characters compare not-equal. | 6340 // Fall through to here if characters compare not-equal. |
6339 __ mov(r0, Operand(Smi::FromInt(GREATER)), LeaveCC, gt); | 6341 __ mov(r0, Operand(Smi::FromInt(GREATER)), LeaveCC, gt); |
6340 __ mov(r0, Operand(Smi::FromInt(LESS)), LeaveCC, lt); | 6342 __ mov(r0, Operand(Smi::FromInt(LESS)), LeaveCC, lt); |
6341 __ Ret(); | 6343 __ Ret(); |
6342 } | 6344 } |
6343 | 6345 |
6344 | 6346 |
6345 void StringCompareStub::Generate(MacroAssembler* masm) { | 6347 void StringCompareStub::Generate(MacroAssembler* masm) { |
6346 Label runtime; | 6348 Label runtime; |
6347 | 6349 |
| 6350 Counters* counters = masm->isolate()->counters(); |
| 6351 |
6348 // Stack frame on entry. | 6352 // Stack frame on entry. |
6349 // sp[0]: right string | 6353 // sp[0]: right string |
6350 // sp[4]: left string | 6354 // sp[4]: left string |
6351 __ Ldrd(r0 , r1, MemOperand(sp)); // Load right in r0, left in r1. | 6355 __ Ldrd(r0 , r1, MemOperand(sp)); // Load right in r0, left in r1. |
6352 | 6356 |
6353 Label not_same; | 6357 Label not_same; |
6354 __ cmp(r0, r1); | 6358 __ cmp(r0, r1); |
6355 __ b(ne, ¬_same); | 6359 __ b(ne, ¬_same); |
6356 STATIC_ASSERT(EQUAL == 0); | 6360 STATIC_ASSERT(EQUAL == 0); |
6357 STATIC_ASSERT(kSmiTag == 0); | 6361 STATIC_ASSERT(kSmiTag == 0); |
6358 __ mov(r0, Operand(Smi::FromInt(EQUAL))); | 6362 __ mov(r0, Operand(Smi::FromInt(EQUAL))); |
6359 __ IncrementCounter(COUNTERS->string_compare_native(), 1, r1, r2); | 6363 __ IncrementCounter(counters->string_compare_native(), 1, r1, r2); |
6360 __ add(sp, sp, Operand(2 * kPointerSize)); | 6364 __ add(sp, sp, Operand(2 * kPointerSize)); |
6361 __ Ret(); | 6365 __ Ret(); |
6362 | 6366 |
6363 __ bind(¬_same); | 6367 __ bind(¬_same); |
6364 | 6368 |
6365 // Check that both objects are sequential ASCII strings. | 6369 // Check that both objects are sequential ASCII strings. |
6366 __ JumpIfNotBothSequentialAsciiStrings(r1, r0, r2, r3, &runtime); | 6370 __ JumpIfNotBothSequentialAsciiStrings(r1, r0, r2, r3, &runtime); |
6367 | 6371 |
6368 // Compare flat ASCII strings natively. Remove arguments from stack first. | 6372 // Compare flat ASCII strings natively. Remove arguments from stack first. |
6369 __ IncrementCounter(COUNTERS->string_compare_native(), 1, r2, r3); | 6373 __ IncrementCounter(counters->string_compare_native(), 1, r2, r3); |
6370 __ add(sp, sp, Operand(2 * kPointerSize)); | 6374 __ add(sp, sp, Operand(2 * kPointerSize)); |
6371 GenerateCompareFlatAsciiStrings(masm, r1, r0, r2, r3, r4, r5); | 6375 GenerateCompareFlatAsciiStrings(masm, r1, r0, r2, r3, r4, r5); |
6372 | 6376 |
6373 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 6377 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
6374 // tagged as a small integer. | 6378 // tagged as a small integer. |
6375 __ bind(&runtime); | 6379 __ bind(&runtime); |
6376 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 6380 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
6377 } | 6381 } |
6378 | 6382 |
6379 | 6383 |
6380 void StringAddStub::Generate(MacroAssembler* masm) { | 6384 void StringAddStub::Generate(MacroAssembler* masm) { |
6381 Label string_add_runtime, call_builtin; | 6385 Label string_add_runtime, call_builtin; |
6382 Builtins::JavaScript builtin_id = Builtins::ADD; | 6386 Builtins::JavaScript builtin_id = Builtins::ADD; |
6383 | 6387 |
| 6388 Counters* counters = masm->isolate()->counters(); |
| 6389 |
6384 // Stack on entry: | 6390 // Stack on entry: |
6385 // sp[0]: second argument (right). | 6391 // sp[0]: second argument (right). |
6386 // sp[4]: first argument (left). | 6392 // sp[4]: first argument (left). |
6387 | 6393 |
6388 // Load the two arguments. | 6394 // Load the two arguments. |
6389 __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); // First argument. | 6395 __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); // First argument. |
6390 __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); // Second argument. | 6396 __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); // Second argument. |
6391 | 6397 |
6392 // Make sure that both arguments are strings if not known in advance. | 6398 // Make sure that both arguments are strings if not known in advance. |
6393 if (flags_ == NO_STRING_ADD_FLAGS) { | 6399 if (flags_ == NO_STRING_ADD_FLAGS) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6429 __ ldr(r2, FieldMemOperand(r0, String::kLengthOffset)); | 6435 __ ldr(r2, FieldMemOperand(r0, String::kLengthOffset)); |
6430 __ ldr(r3, FieldMemOperand(r1, String::kLengthOffset)); | 6436 __ ldr(r3, FieldMemOperand(r1, String::kLengthOffset)); |
6431 STATIC_ASSERT(kSmiTag == 0); | 6437 STATIC_ASSERT(kSmiTag == 0); |
6432 __ cmp(r2, Operand(Smi::FromInt(0))); // Test if first string is empty. | 6438 __ cmp(r2, Operand(Smi::FromInt(0))); // Test if first string is empty. |
6433 __ mov(r0, Operand(r1), LeaveCC, eq); // If first is empty, return second. | 6439 __ mov(r0, Operand(r1), LeaveCC, eq); // If first is empty, return second. |
6434 STATIC_ASSERT(kSmiTag == 0); | 6440 STATIC_ASSERT(kSmiTag == 0); |
6435 // Else test if second string is empty. | 6441 // Else test if second string is empty. |
6436 __ cmp(r3, Operand(Smi::FromInt(0)), ne); | 6442 __ cmp(r3, Operand(Smi::FromInt(0)), ne); |
6437 __ b(ne, &strings_not_empty); // If either string was empty, return r0. | 6443 __ b(ne, &strings_not_empty); // If either string was empty, return r0. |
6438 | 6444 |
6439 __ IncrementCounter(COUNTERS->string_add_native(), 1, r2, r3); | 6445 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); |
6440 __ add(sp, sp, Operand(2 * kPointerSize)); | 6446 __ add(sp, sp, Operand(2 * kPointerSize)); |
6441 __ Ret(); | 6447 __ Ret(); |
6442 | 6448 |
6443 __ bind(&strings_not_empty); | 6449 __ bind(&strings_not_empty); |
6444 } | 6450 } |
6445 | 6451 |
6446 __ mov(r2, Operand(r2, ASR, kSmiTagSize)); | 6452 __ mov(r2, Operand(r2, ASR, kSmiTagSize)); |
6447 __ mov(r3, Operand(r3, ASR, kSmiTagSize)); | 6453 __ mov(r3, Operand(r3, ASR, kSmiTagSize)); |
6448 // Both strings are non-empty. | 6454 // Both strings are non-empty. |
6449 // r0: first string | 6455 // r0: first string |
(...skipping 24 matching lines...) Expand all Loading... |
6474 | 6480 |
6475 // Get the two characters forming the sub string. | 6481 // Get the two characters forming the sub string. |
6476 __ ldrb(r2, FieldMemOperand(r0, SeqAsciiString::kHeaderSize)); | 6482 __ ldrb(r2, FieldMemOperand(r0, SeqAsciiString::kHeaderSize)); |
6477 __ ldrb(r3, FieldMemOperand(r1, SeqAsciiString::kHeaderSize)); | 6483 __ ldrb(r3, FieldMemOperand(r1, SeqAsciiString::kHeaderSize)); |
6478 | 6484 |
6479 // Try to lookup two character string in symbol table. If it is not found | 6485 // Try to lookup two character string in symbol table. If it is not found |
6480 // just allocate a new one. | 6486 // just allocate a new one. |
6481 Label make_two_character_string; | 6487 Label make_two_character_string; |
6482 StringHelper::GenerateTwoCharacterSymbolTableProbe( | 6488 StringHelper::GenerateTwoCharacterSymbolTableProbe( |
6483 masm, r2, r3, r6, r7, r4, r5, r9, &make_two_character_string); | 6489 masm, r2, r3, r6, r7, r4, r5, r9, &make_two_character_string); |
6484 __ IncrementCounter(COUNTERS->string_add_native(), 1, r2, r3); | 6490 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); |
6485 __ add(sp, sp, Operand(2 * kPointerSize)); | 6491 __ add(sp, sp, Operand(2 * kPointerSize)); |
6486 __ Ret(); | 6492 __ Ret(); |
6487 | 6493 |
6488 __ bind(&make_two_character_string); | 6494 __ bind(&make_two_character_string); |
6489 // Resulting string has length 2 and first chars of two strings | 6495 // Resulting string has length 2 and first chars of two strings |
6490 // are combined into single halfword in r2 register. | 6496 // are combined into single halfword in r2 register. |
6491 // So we can fill resulting string without two loops by a single | 6497 // So we can fill resulting string without two loops by a single |
6492 // halfword store instruction (which assumes that processor is | 6498 // halfword store instruction (which assumes that processor is |
6493 // in a little endian mode) | 6499 // in a little endian mode) |
6494 __ mov(r6, Operand(2)); | 6500 __ mov(r6, Operand(2)); |
6495 __ AllocateAsciiString(r0, r6, r4, r5, r9, &string_add_runtime); | 6501 __ AllocateAsciiString(r0, r6, r4, r5, r9, &string_add_runtime); |
6496 __ strh(r2, FieldMemOperand(r0, SeqAsciiString::kHeaderSize)); | 6502 __ strh(r2, FieldMemOperand(r0, SeqAsciiString::kHeaderSize)); |
6497 __ IncrementCounter(COUNTERS->string_add_native(), 1, r2, r3); | 6503 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); |
6498 __ add(sp, sp, Operand(2 * kPointerSize)); | 6504 __ add(sp, sp, Operand(2 * kPointerSize)); |
6499 __ Ret(); | 6505 __ Ret(); |
6500 | 6506 |
6501 __ bind(&longer_than_two); | 6507 __ bind(&longer_than_two); |
6502 // Check if resulting string will be flat. | 6508 // Check if resulting string will be flat. |
6503 __ cmp(r6, Operand(String::kMinNonFlatLength)); | 6509 __ cmp(r6, Operand(String::kMinNonFlatLength)); |
6504 __ b(lt, &string_add_flat_result); | 6510 __ b(lt, &string_add_flat_result); |
6505 // Handle exceptionally long strings in the runtime system. | 6511 // Handle exceptionally long strings in the runtime system. |
6506 STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0); | 6512 STATIC_ASSERT((String::kMaxLength & 0x80000000) == 0); |
6507 ASSERT(IsPowerOf2(String::kMaxLength + 1)); | 6513 ASSERT(IsPowerOf2(String::kMaxLength + 1)); |
(...skipping 16 matching lines...) Expand all Loading... |
6524 __ b(eq, &non_ascii); | 6530 __ b(eq, &non_ascii); |
6525 | 6531 |
6526 // Allocate an ASCII cons string. | 6532 // Allocate an ASCII cons string. |
6527 __ bind(&ascii_data); | 6533 __ bind(&ascii_data); |
6528 __ AllocateAsciiConsString(r7, r6, r4, r5, &string_add_runtime); | 6534 __ AllocateAsciiConsString(r7, r6, r4, r5, &string_add_runtime); |
6529 __ bind(&allocated); | 6535 __ bind(&allocated); |
6530 // Fill the fields of the cons string. | 6536 // Fill the fields of the cons string. |
6531 __ str(r0, FieldMemOperand(r7, ConsString::kFirstOffset)); | 6537 __ str(r0, FieldMemOperand(r7, ConsString::kFirstOffset)); |
6532 __ str(r1, FieldMemOperand(r7, ConsString::kSecondOffset)); | 6538 __ str(r1, FieldMemOperand(r7, ConsString::kSecondOffset)); |
6533 __ mov(r0, Operand(r7)); | 6539 __ mov(r0, Operand(r7)); |
6534 __ IncrementCounter(COUNTERS->string_add_native(), 1, r2, r3); | 6540 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); |
6535 __ add(sp, sp, Operand(2 * kPointerSize)); | 6541 __ add(sp, sp, Operand(2 * kPointerSize)); |
6536 __ Ret(); | 6542 __ Ret(); |
6537 | 6543 |
6538 __ bind(&non_ascii); | 6544 __ bind(&non_ascii); |
6539 // At least one of the strings is two-byte. Check whether it happens | 6545 // At least one of the strings is two-byte. Check whether it happens |
6540 // to contain only ASCII characters. | 6546 // to contain only ASCII characters. |
6541 // r4: first instance type. | 6547 // r4: first instance type. |
6542 // r5: second instance type. | 6548 // r5: second instance type. |
6543 __ tst(r4, Operand(kAsciiDataHintMask)); | 6549 __ tst(r4, Operand(kAsciiDataHintMask)); |
6544 __ tst(r5, Operand(kAsciiDataHintMask), ne); | 6550 __ tst(r5, Operand(kAsciiDataHintMask), ne); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6606 StringHelper::GenerateCopyCharacters(masm, r6, r0, r2, r4, true); | 6612 StringHelper::GenerateCopyCharacters(masm, r6, r0, r2, r4, true); |
6607 | 6613 |
6608 // Load second argument and locate first character. | 6614 // Load second argument and locate first character. |
6609 __ add(r1, r1, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); | 6615 __ add(r1, r1, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); |
6610 // r1: first character of second string. | 6616 // r1: first character of second string. |
6611 // r3: length of second string. | 6617 // r3: length of second string. |
6612 // r6: next character of result. | 6618 // r6: next character of result. |
6613 // r7: result string. | 6619 // r7: result string. |
6614 StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, true); | 6620 StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, true); |
6615 __ mov(r0, Operand(r7)); | 6621 __ mov(r0, Operand(r7)); |
6616 __ IncrementCounter(COUNTERS->string_add_native(), 1, r2, r3); | 6622 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); |
6617 __ add(sp, sp, Operand(2 * kPointerSize)); | 6623 __ add(sp, sp, Operand(2 * kPointerSize)); |
6618 __ Ret(); | 6624 __ Ret(); |
6619 | 6625 |
6620 __ bind(&non_ascii_string_add_flat_result); | 6626 __ bind(&non_ascii_string_add_flat_result); |
6621 // Both strings are sequential two byte strings. | 6627 // Both strings are sequential two byte strings. |
6622 // r0: first string. | 6628 // r0: first string. |
6623 // r1: second string. | 6629 // r1: second string. |
6624 // r2: length of first string. | 6630 // r2: length of first string. |
6625 // r3: length of second string. | 6631 // r3: length of second string. |
6626 // r6: sum of length of strings. | 6632 // r6: sum of length of strings. |
(...skipping 20 matching lines...) Expand all Loading... |
6647 // Locate first character of second argument. | 6653 // Locate first character of second argument. |
6648 __ add(r1, r1, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); | 6654 __ add(r1, r1, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); |
6649 | 6655 |
6650 // r1: first character of second string. | 6656 // r1: first character of second string. |
6651 // r3: length of second string. | 6657 // r3: length of second string. |
6652 // r6: next character of result (after copy of first string). | 6658 // r6: next character of result (after copy of first string). |
6653 // r7: result string. | 6659 // r7: result string. |
6654 StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, false); | 6660 StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, false); |
6655 | 6661 |
6656 __ mov(r0, Operand(r7)); | 6662 __ mov(r0, Operand(r7)); |
6657 __ IncrementCounter(COUNTERS->string_add_native(), 1, r2, r3); | 6663 __ IncrementCounter(counters->string_add_native(), 1, r2, r3); |
6658 __ add(sp, sp, Operand(2 * kPointerSize)); | 6664 __ add(sp, sp, Operand(2 * kPointerSize)); |
6659 __ Ret(); | 6665 __ Ret(); |
6660 | 6666 |
6661 // Just jump to runtime to add the two strings. | 6667 // Just jump to runtime to add the two strings. |
6662 __ bind(&string_add_runtime); | 6668 __ bind(&string_add_runtime); |
6663 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 6669 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
6664 | 6670 |
6665 if (call_builtin.is_linked()) { | 6671 if (call_builtin.is_linked()) { |
6666 __ bind(&call_builtin); | 6672 __ bind(&call_builtin); |
6667 __ InvokeBuiltin(builtin_id, JUMP_JS); | 6673 __ InvokeBuiltin(builtin_id, JUMP_JS); |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6858 __ str(pc, MemOperand(sp, 0)); | 6864 __ str(pc, MemOperand(sp, 0)); |
6859 __ Jump(target); // Call the C++ function. | 6865 __ Jump(target); // Call the C++ function. |
6860 } | 6866 } |
6861 | 6867 |
6862 | 6868 |
6863 #undef __ | 6869 #undef __ |
6864 | 6870 |
6865 } } // namespace v8::internal | 6871 } } // namespace v8::internal |
6866 | 6872 |
6867 #endif // V8_TARGET_ARCH_ARM | 6873 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |