| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 553 | 553 |
| 554 Label not_special; | 554 Label not_special; |
| 555 // Convert from Smi to integer. | 555 // Convert from Smi to integer. |
| 556 __ mov(source_, Operand(source_, ASR, kSmiTagSize)); | 556 __ mov(source_, Operand(source_, ASR, kSmiTagSize)); |
| 557 // Move sign bit from source to destination. This works because the sign bit | 557 // Move sign bit from source to destination. This works because the sign bit |
| 558 // in the exponent word of the double has the same position and polarity as | 558 // in the exponent word of the double has the same position and polarity as |
| 559 // the 2's complement sign bit in a Smi. | 559 // the 2's complement sign bit in a Smi. |
| 560 STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u); | 560 STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u); |
| 561 __ and_(exponent, source_, Operand(HeapNumber::kSignMask), SetCC); | 561 __ and_(exponent, source_, Operand(HeapNumber::kSignMask), SetCC); |
| 562 // Subtract from 0 if source was negative. | 562 // Subtract from 0 if source was negative. |
| 563 __ rsb(source_, source_, Operand(0, RelocInfo::NONE), LeaveCC, ne); | 563 __ rsb(source_, source_, Operand(0, RelocInfo::NONE32), LeaveCC, ne); |
| 564 | 564 |
| 565 // We have -1, 0 or 1, which we treat specially. Register source_ contains | 565 // We have -1, 0 or 1, which we treat specially. Register source_ contains |
| 566 // absolute value: it is either equal to 1 (special case of -1 and 1), | 566 // absolute value: it is either equal to 1 (special case of -1 and 1), |
| 567 // greater than 1 (not a special case) or less than 1 (special case of 0). | 567 // greater than 1 (not a special case) or less than 1 (special case of 0). |
| 568 __ cmp(source_, Operand(1)); | 568 __ cmp(source_, Operand(1)); |
| 569 __ b(gt, ¬_special); | 569 __ b(gt, ¬_special); |
| 570 | 570 |
| 571 // For 1 or -1 we need to or in the 0 exponent (biased to 1023). | 571 // For 1 or -1 we need to or in the 0 exponent (biased to 1023). |
| 572 const uint32_t exponent_word_for_1 = | 572 const uint32_t exponent_word_for_1 = |
| 573 HeapNumber::kExponentBias << HeapNumber::kExponentShift; | 573 HeapNumber::kExponentBias << HeapNumber::kExponentShift; |
| 574 __ orr(exponent, exponent, Operand(exponent_word_for_1), LeaveCC, eq); | 574 __ orr(exponent, exponent, Operand(exponent_word_for_1), LeaveCC, eq); |
| 575 // 1, 0 and -1 all have 0 for the second word. | 575 // 1, 0 and -1 all have 0 for the second word. |
| 576 __ mov(mantissa, Operand(0, RelocInfo::NONE)); | 576 __ mov(mantissa, Operand(0, RelocInfo::NONE32)); |
| 577 __ Ret(); | 577 __ Ret(); |
| 578 | 578 |
| 579 __ bind(¬_special); | 579 __ bind(¬_special); |
| 580 // Count leading zeros. Uses mantissa for a scratch register on pre-ARM5. | 580 // Count leading zeros. Uses mantissa for a scratch register on pre-ARM5. |
| 581 // Gets the wrong answer for 0, but we already checked for that case above. | 581 // Gets the wrong answer for 0, but we already checked for that case above. |
| 582 __ CountLeadingZeros(zeros_, source_, mantissa); | 582 __ CountLeadingZeros(zeros_, source_, mantissa); |
| 583 // Compute exponent and or it into the exponent register. | 583 // Compute exponent and or it into the exponent register. |
| 584 // We use mantissa as a scratch register here. Use a fudge factor to | 584 // We use mantissa as a scratch register here. Use a fudge factor to |
| 585 // divide the constant 31 + HeapNumber::kExponentBias, 0x41d, into two parts | 585 // divide the constant 31 + HeapNumber::kExponentBias, 0x41d, into two parts |
| 586 // that fit in the ARM's constant field. | 586 // that fit in the ARM's constant field. |
| (...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1134 __ cmp(the_int_, Operand(0x80000000u)); | 1134 __ cmp(the_int_, Operand(0x80000000u)); |
| 1135 __ b(eq, &max_negative_int); | 1135 __ b(eq, &max_negative_int); |
| 1136 // Set up the correct exponent in scratch_. All non-Smi int32s have the same. | 1136 // Set up the correct exponent in scratch_. All non-Smi int32s have the same. |
| 1137 // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased). | 1137 // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased). |
| 1138 uint32_t non_smi_exponent = | 1138 uint32_t non_smi_exponent = |
| 1139 (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift; | 1139 (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift; |
| 1140 __ mov(scratch_, Operand(non_smi_exponent)); | 1140 __ mov(scratch_, Operand(non_smi_exponent)); |
| 1141 // Set the sign bit in scratch_ if the value was negative. | 1141 // Set the sign bit in scratch_ if the value was negative. |
| 1142 __ orr(scratch_, scratch_, Operand(HeapNumber::kSignMask), LeaveCC, cs); | 1142 __ orr(scratch_, scratch_, Operand(HeapNumber::kSignMask), LeaveCC, cs); |
| 1143 // Subtract from 0 if the value was negative. | 1143 // Subtract from 0 if the value was negative. |
| 1144 __ rsb(the_int_, the_int_, Operand(0, RelocInfo::NONE), LeaveCC, cs); | 1144 __ rsb(the_int_, the_int_, Operand(0, RelocInfo::NONE32), LeaveCC, cs); |
| 1145 // We should be masking the implict first digit of the mantissa away here, | 1145 // We should be masking the implict first digit of the mantissa away here, |
| 1146 // but it just ends up combining harmlessly with the last digit of the | 1146 // but it just ends up combining harmlessly with the last digit of the |
| 1147 // exponent that happens to be 1. The sign bit is 0 so we shift 10 to get | 1147 // exponent that happens to be 1. The sign bit is 0 so we shift 10 to get |
| 1148 // the most significant 1 to hit the last bit of the 12 bit sign and exponent. | 1148 // the most significant 1 to hit the last bit of the 12 bit sign and exponent. |
| 1149 ASSERT(((1 << HeapNumber::kExponentShift) & non_smi_exponent) != 0); | 1149 ASSERT(((1 << HeapNumber::kExponentShift) & non_smi_exponent) != 0); |
| 1150 const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2; | 1150 const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2; |
| 1151 __ orr(scratch_, scratch_, Operand(the_int_, LSR, shift_distance)); | 1151 __ orr(scratch_, scratch_, Operand(the_int_, LSR, shift_distance)); |
| 1152 __ str(scratch_, FieldMemOperand(the_heap_number_, | 1152 __ str(scratch_, FieldMemOperand(the_heap_number_, |
| 1153 HeapNumber::kExponentOffset)); | 1153 HeapNumber::kExponentOffset)); |
| 1154 __ mov(scratch_, Operand(the_int_, LSL, 32 - shift_distance)); | 1154 __ mov(scratch_, Operand(the_int_, LSL, 32 - shift_distance)); |
| 1155 __ str(scratch_, FieldMemOperand(the_heap_number_, | 1155 __ str(scratch_, FieldMemOperand(the_heap_number_, |
| 1156 HeapNumber::kMantissaOffset)); | 1156 HeapNumber::kMantissaOffset)); |
| 1157 __ Ret(); | 1157 __ Ret(); |
| 1158 | 1158 |
| 1159 __ bind(&max_negative_int); | 1159 __ bind(&max_negative_int); |
| 1160 // The max negative int32 is stored as a positive number in the mantissa of | 1160 // The max negative int32 is stored as a positive number in the mantissa of |
| 1161 // a double because it uses a sign bit instead of using two's complement. | 1161 // a double because it uses a sign bit instead of using two's complement. |
| 1162 // The actual mantissa bits stored are all 0 because the implicit most | 1162 // The actual mantissa bits stored are all 0 because the implicit most |
| 1163 // significant 1 bit is not stored. | 1163 // significant 1 bit is not stored. |
| 1164 non_smi_exponent += 1 << HeapNumber::kExponentShift; | 1164 non_smi_exponent += 1 << HeapNumber::kExponentShift; |
| 1165 __ mov(ip, Operand(HeapNumber::kSignMask | non_smi_exponent)); | 1165 __ mov(ip, Operand(HeapNumber::kSignMask | non_smi_exponent)); |
| 1166 __ str(ip, FieldMemOperand(the_heap_number_, HeapNumber::kExponentOffset)); | 1166 __ str(ip, FieldMemOperand(the_heap_number_, HeapNumber::kExponentOffset)); |
| 1167 __ mov(ip, Operand(0, RelocInfo::NONE)); | 1167 __ mov(ip, Operand(0, RelocInfo::NONE32)); |
| 1168 __ str(ip, FieldMemOperand(the_heap_number_, HeapNumber::kMantissaOffset)); | 1168 __ str(ip, FieldMemOperand(the_heap_number_, HeapNumber::kMantissaOffset)); |
| 1169 __ Ret(); | 1169 __ Ret(); |
| 1170 } | 1170 } |
| 1171 | 1171 |
| 1172 | 1172 |
| 1173 // Handle the case where the lhs and rhs are the same object. | 1173 // Handle the case where the lhs and rhs are the same object. |
| 1174 // Equality is almost reflexive (everything but NaN), so this is a test | 1174 // Equality is almost reflexive (everything but NaN), so this is a test |
| 1175 // for "identity and not NaN". | 1175 // for "identity and not NaN". |
| 1176 static void EmitIdenticalObjectComparison(MacroAssembler* masm, | 1176 static void EmitIdenticalObjectComparison(MacroAssembler* masm, |
| 1177 Label* slow, | 1177 Label* slow, |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1373 lhs_exponent, | 1373 lhs_exponent, |
| 1374 HeapNumber::kExponentShift, | 1374 HeapNumber::kExponentShift, |
| 1375 HeapNumber::kExponentBits); | 1375 HeapNumber::kExponentBits); |
| 1376 // NaNs have all-one exponents so they sign extend to -1. | 1376 // NaNs have all-one exponents so they sign extend to -1. |
| 1377 __ cmp(r4, Operand(-1)); | 1377 __ cmp(r4, Operand(-1)); |
| 1378 __ b(ne, lhs_not_nan); | 1378 __ b(ne, lhs_not_nan); |
| 1379 __ mov(r4, | 1379 __ mov(r4, |
| 1380 Operand(lhs_exponent, LSL, HeapNumber::kNonMantissaBitsInTopWord), | 1380 Operand(lhs_exponent, LSL, HeapNumber::kNonMantissaBitsInTopWord), |
| 1381 SetCC); | 1381 SetCC); |
| 1382 __ b(ne, &one_is_nan); | 1382 __ b(ne, &one_is_nan); |
| 1383 __ cmp(lhs_mantissa, Operand(0, RelocInfo::NONE)); | 1383 __ cmp(lhs_mantissa, Operand(0, RelocInfo::NONE32)); |
| 1384 __ b(ne, &one_is_nan); | 1384 __ b(ne, &one_is_nan); |
| 1385 | 1385 |
| 1386 __ bind(lhs_not_nan); | 1386 __ bind(lhs_not_nan); |
| 1387 __ Sbfx(r4, | 1387 __ Sbfx(r4, |
| 1388 rhs_exponent, | 1388 rhs_exponent, |
| 1389 HeapNumber::kExponentShift, | 1389 HeapNumber::kExponentShift, |
| 1390 HeapNumber::kExponentBits); | 1390 HeapNumber::kExponentBits); |
| 1391 // NaNs have all-one exponents so they sign extend to -1. | 1391 // NaNs have all-one exponents so they sign extend to -1. |
| 1392 __ cmp(r4, Operand(-1)); | 1392 __ cmp(r4, Operand(-1)); |
| 1393 __ b(ne, &neither_is_nan); | 1393 __ b(ne, &neither_is_nan); |
| 1394 __ mov(r4, | 1394 __ mov(r4, |
| 1395 Operand(rhs_exponent, LSL, HeapNumber::kNonMantissaBitsInTopWord), | 1395 Operand(rhs_exponent, LSL, HeapNumber::kNonMantissaBitsInTopWord), |
| 1396 SetCC); | 1396 SetCC); |
| 1397 __ b(ne, &one_is_nan); | 1397 __ b(ne, &one_is_nan); |
| 1398 __ cmp(rhs_mantissa, Operand(0, RelocInfo::NONE)); | 1398 __ cmp(rhs_mantissa, Operand(0, RelocInfo::NONE32)); |
| 1399 __ b(eq, &neither_is_nan); | 1399 __ b(eq, &neither_is_nan); |
| 1400 | 1400 |
| 1401 __ bind(&one_is_nan); | 1401 __ bind(&one_is_nan); |
| 1402 // NaN comparisons always fail. | 1402 // NaN comparisons always fail. |
| 1403 // Load whatever we need in r0 to make the comparison fail. | 1403 // Load whatever we need in r0 to make the comparison fail. |
| 1404 if (cond == lt || cond == le) { | 1404 if (cond == lt || cond == le) { |
| 1405 __ mov(r0, Operand(GREATER)); | 1405 __ mov(r0, Operand(GREATER)); |
| 1406 } else { | 1406 } else { |
| 1407 __ mov(r0, Operand(LESS)); | 1407 __ mov(r0, Operand(LESS)); |
| 1408 } | 1408 } |
| (...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1915 __ JumpIfSmi(tos_, &patch); | 1915 __ JumpIfSmi(tos_, &patch); |
| 1916 } | 1916 } |
| 1917 | 1917 |
| 1918 if (types_.NeedsMap()) { | 1918 if (types_.NeedsMap()) { |
| 1919 __ ldr(map, FieldMemOperand(tos_, HeapObject::kMapOffset)); | 1919 __ ldr(map, FieldMemOperand(tos_, HeapObject::kMapOffset)); |
| 1920 | 1920 |
| 1921 if (types_.CanBeUndetectable()) { | 1921 if (types_.CanBeUndetectable()) { |
| 1922 __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset)); | 1922 __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset)); |
| 1923 __ tst(ip, Operand(1 << Map::kIsUndetectable)); | 1923 __ tst(ip, Operand(1 << Map::kIsUndetectable)); |
| 1924 // Undetectable -> false. | 1924 // Undetectable -> false. |
| 1925 __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, ne); | 1925 __ mov(tos_, Operand(0, RelocInfo::NONE32), LeaveCC, ne); |
| 1926 __ Ret(ne); | 1926 __ Ret(ne); |
| 1927 } | 1927 } |
| 1928 } | 1928 } |
| 1929 | 1929 |
| 1930 if (types_.Contains(SPEC_OBJECT)) { | 1930 if (types_.Contains(SPEC_OBJECT)) { |
| 1931 // Spec object -> true. | 1931 // Spec object -> true. |
| 1932 __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE); | 1932 __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE); |
| 1933 // tos_ contains the correct non-zero return value already. | 1933 // tos_ contains the correct non-zero return value already. |
| 1934 __ Ret(ge); | 1934 __ Ret(ge); |
| 1935 } | 1935 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1948 __ b(ne, ¬_heap_number); | 1948 __ b(ne, ¬_heap_number); |
| 1949 | 1949 |
| 1950 if (CpuFeatures::IsSupported(VFP2)) { | 1950 if (CpuFeatures::IsSupported(VFP2)) { |
| 1951 CpuFeatures::Scope scope(VFP2); | 1951 CpuFeatures::Scope scope(VFP2); |
| 1952 | 1952 |
| 1953 __ vldr(d1, FieldMemOperand(tos_, HeapNumber::kValueOffset)); | 1953 __ vldr(d1, FieldMemOperand(tos_, HeapNumber::kValueOffset)); |
| 1954 __ VFPCompareAndSetFlags(d1, 0.0); | 1954 __ VFPCompareAndSetFlags(d1, 0.0); |
| 1955 // "tos_" is a register, and contains a non zero value by default. | 1955 // "tos_" is a register, and contains a non zero value by default. |
| 1956 // Hence we only need to overwrite "tos_" with zero to return false for | 1956 // Hence we only need to overwrite "tos_" with zero to return false for |
| 1957 // FP_ZERO or FP_NAN cases. Otherwise, by default it returns true. | 1957 // FP_ZERO or FP_NAN cases. Otherwise, by default it returns true. |
| 1958 __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, eq); // for FP_ZERO | 1958 __ mov(tos_, Operand(0, RelocInfo::NONE32), LeaveCC, eq); // for FP_ZERO |
| 1959 __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, vs); // for FP_NAN | 1959 __ mov(tos_, Operand(0, RelocInfo::NONE32), LeaveCC, vs); // for FP_NAN |
| 1960 } else { | 1960 } else { |
| 1961 Label done, not_nan, not_zero; | 1961 Label done, not_nan, not_zero; |
| 1962 __ ldr(temp, FieldMemOperand(tos_, HeapNumber::kExponentOffset)); | 1962 __ ldr(temp, FieldMemOperand(tos_, HeapNumber::kExponentOffset)); |
| 1963 // -0 maps to false: | 1963 // -0 maps to false: |
| 1964 __ bic( | 1964 __ bic( |
| 1965 temp, temp, Operand(HeapNumber::kSignMask, RelocInfo::NONE), SetCC); | 1965 temp, temp, Operand(HeapNumber::kSignMask, RelocInfo::NONE32), SetCC); |
| 1966 __ b(ne, ¬_zero); | 1966 __ b(ne, ¬_zero); |
| 1967 // If exponent word is zero then the answer depends on the mantissa word. | 1967 // If exponent word is zero then the answer depends on the mantissa word. |
| 1968 __ ldr(tos_, FieldMemOperand(tos_, HeapNumber::kMantissaOffset)); | 1968 __ ldr(tos_, FieldMemOperand(tos_, HeapNumber::kMantissaOffset)); |
| 1969 __ jmp(&done); | 1969 __ jmp(&done); |
| 1970 | 1970 |
| 1971 // Check for NaN. | 1971 // Check for NaN. |
| 1972 __ bind(¬_zero); | 1972 __ bind(¬_zero); |
| 1973 // We already zeroed the sign bit, now shift out the mantissa so we only | 1973 // We already zeroed the sign bit, now shift out the mantissa so we only |
| 1974 // have the exponent left. | 1974 // have the exponent left. |
| 1975 __ mov(temp, Operand(temp, LSR, HeapNumber::kMantissaBitsInTopWord)); | 1975 __ mov(temp, Operand(temp, LSR, HeapNumber::kMantissaBitsInTopWord)); |
| 1976 unsigned int shifted_exponent_mask = | 1976 unsigned int shifted_exponent_mask = |
| 1977 HeapNumber::kExponentMask >> HeapNumber::kMantissaBitsInTopWord; | 1977 HeapNumber::kExponentMask >> HeapNumber::kMantissaBitsInTopWord; |
| 1978 __ cmp(temp, Operand(shifted_exponent_mask, RelocInfo::NONE)); | 1978 __ cmp(temp, Operand(shifted_exponent_mask, RelocInfo::NONE32)); |
| 1979 __ b(ne, ¬_nan); // If exponent is not 0x7ff then it can't be a NaN. | 1979 __ b(ne, ¬_nan); // If exponent is not 0x7ff then it can't be a NaN. |
| 1980 | 1980 |
| 1981 // Reload exponent word. | 1981 // Reload exponent word. |
| 1982 __ ldr(temp, FieldMemOperand(tos_, HeapNumber::kExponentOffset)); | 1982 __ ldr(temp, FieldMemOperand(tos_, HeapNumber::kExponentOffset)); |
| 1983 __ tst(temp, Operand(HeapNumber::kMantissaMask, RelocInfo::NONE)); | 1983 __ tst(temp, Operand(HeapNumber::kMantissaMask, RelocInfo::NONE32)); |
| 1984 // If mantissa is not zero then we have a NaN, so return 0. | 1984 // If mantissa is not zero then we have a NaN, so return 0. |
| 1985 __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, ne); | 1985 __ mov(tos_, Operand(0, RelocInfo::NONE32), LeaveCC, ne); |
| 1986 __ b(ne, &done); | 1986 __ b(ne, &done); |
| 1987 | 1987 |
| 1988 // Load mantissa word. | 1988 // Load mantissa word. |
| 1989 __ ldr(temp, FieldMemOperand(tos_, HeapNumber::kMantissaOffset)); | 1989 __ ldr(temp, FieldMemOperand(tos_, HeapNumber::kMantissaOffset)); |
| 1990 __ cmp(temp, Operand(0, RelocInfo::NONE)); | 1990 __ cmp(temp, Operand(0, RelocInfo::NONE32)); |
| 1991 // If mantissa is not zero then we have a NaN, so return 0. | 1991 // If mantissa is not zero then we have a NaN, so return 0. |
| 1992 __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, ne); | 1992 __ mov(tos_, Operand(0, RelocInfo::NONE32), LeaveCC, ne); |
| 1993 __ b(ne, &done); | 1993 __ b(ne, &done); |
| 1994 | 1994 |
| 1995 __ bind(¬_nan); | 1995 __ bind(¬_nan); |
| 1996 __ mov(tos_, Operand(1, RelocInfo::NONE)); | 1996 __ mov(tos_, Operand(1, RelocInfo::NONE32)); |
| 1997 __ bind(&done); | 1997 __ bind(&done); |
| 1998 } | 1998 } |
| 1999 __ Ret(); | 1999 __ Ret(); |
| 2000 __ bind(¬_heap_number); | 2000 __ bind(¬_heap_number); |
| 2001 } | 2001 } |
| 2002 | 2002 |
| 2003 __ bind(&patch); | 2003 __ bind(&patch); |
| 2004 GenerateTypeTransition(masm); | 2004 GenerateTypeTransition(masm); |
| 2005 } | 2005 } |
| 2006 | 2006 |
| 2007 | 2007 |
| 2008 void ToBooleanStub::CheckOddball(MacroAssembler* masm, | 2008 void ToBooleanStub::CheckOddball(MacroAssembler* masm, |
| 2009 Type type, | 2009 Type type, |
| 2010 Heap::RootListIndex value, | 2010 Heap::RootListIndex value, |
| 2011 bool result) { | 2011 bool result) { |
| 2012 if (types_.Contains(type)) { | 2012 if (types_.Contains(type)) { |
| 2013 // If we see an expected oddball, return its ToBoolean value tos_. | 2013 // If we see an expected oddball, return its ToBoolean value tos_. |
| 2014 __ LoadRoot(ip, value); | 2014 __ LoadRoot(ip, value); |
| 2015 __ cmp(tos_, ip); | 2015 __ cmp(tos_, ip); |
| 2016 // The value of a root is never NULL, so we can avoid loading a non-null | 2016 // The value of a root is never NULL, so we can avoid loading a non-null |
| 2017 // value into tos_ when we want to return 'true'. | 2017 // value into tos_ when we want to return 'true'. |
| 2018 if (!result) { | 2018 if (!result) { |
| 2019 __ mov(tos_, Operand(0, RelocInfo::NONE), LeaveCC, eq); | 2019 __ mov(tos_, Operand(0, RelocInfo::NONE32), LeaveCC, eq); |
| 2020 } | 2020 } |
| 2021 __ Ret(eq); | 2021 __ Ret(eq); |
| 2022 } | 2022 } |
| 2023 } | 2023 } |
| 2024 | 2024 |
| 2025 | 2025 |
| 2026 void ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) { | 2026 void ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) { |
| 2027 if (!tos_.is(r3)) { | 2027 if (!tos_.is(r3)) { |
| 2028 __ mov(r3, Operand(tos_)); | 2028 __ mov(r3, Operand(tos_)); |
| 2029 } | 2029 } |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2154 void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm, | 2154 void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm, |
| 2155 Label* non_smi, | 2155 Label* non_smi, |
| 2156 Label* slow) { | 2156 Label* slow) { |
| 2157 __ JumpIfNotSmi(r0, non_smi); | 2157 __ JumpIfNotSmi(r0, non_smi); |
| 2158 | 2158 |
| 2159 // The result of negating zero or the smallest negative smi is not a smi. | 2159 // The result of negating zero or the smallest negative smi is not a smi. |
| 2160 __ bic(ip, r0, Operand(0x80000000), SetCC); | 2160 __ bic(ip, r0, Operand(0x80000000), SetCC); |
| 2161 __ b(eq, slow); | 2161 __ b(eq, slow); |
| 2162 | 2162 |
| 2163 // Return '0 - value'. | 2163 // Return '0 - value'. |
| 2164 __ rsb(r0, r0, Operand(0, RelocInfo::NONE)); | 2164 __ rsb(r0, r0, Operand(0, RelocInfo::NONE32)); |
| 2165 __ Ret(); | 2165 __ Ret(); |
| 2166 } | 2166 } |
| 2167 | 2167 |
| 2168 | 2168 |
| 2169 void UnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm, | 2169 void UnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm, |
| 2170 Label* non_smi) { | 2170 Label* non_smi) { |
| 2171 __ JumpIfNotSmi(r0, non_smi); | 2171 __ JumpIfNotSmi(r0, non_smi); |
| 2172 | 2172 |
| 2173 // Flip bits and revert inverted smi-tag. | 2173 // Flip bits and revert inverted smi-tag. |
| 2174 __ mvn(r0, Operand(r0)); | 2174 __ mvn(r0, Operand(r0)); |
| (...skipping 1296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3471 Isolate* isolate = masm->isolate(); | 3471 Isolate* isolate = masm->isolate(); |
| 3472 ExternalReference cache_array = | 3472 ExternalReference cache_array = |
| 3473 ExternalReference::transcendental_cache_array_address(isolate); | 3473 ExternalReference::transcendental_cache_array_address(isolate); |
| 3474 __ mov(cache_entry, Operand(cache_array)); | 3474 __ mov(cache_entry, Operand(cache_array)); |
| 3475 // cache_entry points to cache array. | 3475 // cache_entry points to cache array. |
| 3476 int cache_array_index | 3476 int cache_array_index |
| 3477 = type_ * sizeof(isolate->transcendental_cache()->caches_[0]); | 3477 = type_ * sizeof(isolate->transcendental_cache()->caches_[0]); |
| 3478 __ ldr(cache_entry, MemOperand(cache_entry, cache_array_index)); | 3478 __ ldr(cache_entry, MemOperand(cache_entry, cache_array_index)); |
| 3479 // r0 points to the cache for the type type_. | 3479 // r0 points to the cache for the type type_. |
| 3480 // If NULL, the cache hasn't been initialized yet, so go through runtime. | 3480 // If NULL, the cache hasn't been initialized yet, so go through runtime. |
| 3481 __ cmp(cache_entry, Operand(0, RelocInfo::NONE)); | 3481 __ cmp(cache_entry, Operand(0, RelocInfo::NONE32)); |
| 3482 __ b(eq, &invalid_cache); | 3482 __ b(eq, &invalid_cache); |
| 3483 | 3483 |
| 3484 #ifdef DEBUG | 3484 #ifdef DEBUG |
| 3485 // Check that the layout of cache elements match expectations. | 3485 // Check that the layout of cache elements match expectations. |
| 3486 { TranscendentalCache::SubCache::Element test_elem[2]; | 3486 { TranscendentalCache::SubCache::Element test_elem[2]; |
| 3487 char* elem_start = reinterpret_cast<char*>(&test_elem[0]); | 3487 char* elem_start = reinterpret_cast<char*>(&test_elem[0]); |
| 3488 char* elem2_start = reinterpret_cast<char*>(&test_elem[1]); | 3488 char* elem2_start = reinterpret_cast<char*>(&test_elem[1]); |
| 3489 char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0])); | 3489 char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0])); |
| 3490 char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1])); | 3490 char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1])); |
| 3491 char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output)); | 3491 char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output)); |
| (...skipping 592 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4084 &throw_termination_exception, | 4084 &throw_termination_exception, |
| 4085 &throw_out_of_memory_exception, | 4085 &throw_out_of_memory_exception, |
| 4086 true, | 4086 true, |
| 4087 true); | 4087 true); |
| 4088 | 4088 |
| 4089 __ bind(&throw_out_of_memory_exception); | 4089 __ bind(&throw_out_of_memory_exception); |
| 4090 // Set external caught exception to false. | 4090 // Set external caught exception to false. |
| 4091 Isolate* isolate = masm->isolate(); | 4091 Isolate* isolate = masm->isolate(); |
| 4092 ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress, | 4092 ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress, |
| 4093 isolate); | 4093 isolate); |
| 4094 __ mov(r0, Operand(false, RelocInfo::NONE)); | 4094 __ mov(r0, Operand(false, RelocInfo::NONE32)); |
| 4095 __ mov(r2, Operand(external_caught)); | 4095 __ mov(r2, Operand(external_caught)); |
| 4096 __ str(r0, MemOperand(r2)); | 4096 __ str(r0, MemOperand(r2)); |
| 4097 | 4097 |
| 4098 // Set pending exception and r0 to out of memory exception. | 4098 // Set pending exception and r0 to out of memory exception. |
| 4099 Failure* out_of_memory = Failure::OutOfMemoryException(); | 4099 Failure* out_of_memory = Failure::OutOfMemoryException(); |
| 4100 __ mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory))); | 4100 __ mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory))); |
| 4101 __ mov(r2, Operand(ExternalReference(Isolate::kPendingExceptionAddress, | 4101 __ mov(r2, Operand(ExternalReference(Isolate::kPendingExceptionAddress, |
| 4102 isolate))); | 4102 isolate))); |
| 4103 __ str(r0, MemOperand(r2)); | 4103 __ str(r0, MemOperand(r2)); |
| 4104 // Fall through to the next label. | 4104 // Fall through to the next label. |
| (...skipping 661 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4766 __ ldr(r1, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 4766 __ ldr(r1, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 4767 __ str(r1, MemOperand(sp, 0)); | 4767 __ str(r1, MemOperand(sp, 0)); |
| 4768 __ add(r3, r2, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize)); | 4768 __ add(r3, r2, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 4769 __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset)); | 4769 __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset)); |
| 4770 __ str(r3, MemOperand(sp, 1 * kPointerSize)); | 4770 __ str(r3, MemOperand(sp, 1 * kPointerSize)); |
| 4771 | 4771 |
| 4772 // Try the new space allocation. Start out with computing the size | 4772 // Try the new space allocation. Start out with computing the size |
| 4773 // of the arguments object and the elements array in words. | 4773 // of the arguments object and the elements array in words. |
| 4774 Label add_arguments_object; | 4774 Label add_arguments_object; |
| 4775 __ bind(&try_allocate); | 4775 __ bind(&try_allocate); |
| 4776 __ cmp(r1, Operand(0, RelocInfo::NONE)); | 4776 __ cmp(r1, Operand(0, RelocInfo::NONE32)); |
| 4777 __ b(eq, &add_arguments_object); | 4777 __ b(eq, &add_arguments_object); |
| 4778 __ mov(r1, Operand(r1, LSR, kSmiTagSize)); | 4778 __ mov(r1, Operand(r1, LSR, kSmiTagSize)); |
| 4779 __ add(r1, r1, Operand(FixedArray::kHeaderSize / kPointerSize)); | 4779 __ add(r1, r1, Operand(FixedArray::kHeaderSize / kPointerSize)); |
| 4780 __ bind(&add_arguments_object); | 4780 __ bind(&add_arguments_object); |
| 4781 __ add(r1, r1, Operand(Heap::kArgumentsObjectSizeStrict / kPointerSize)); | 4781 __ add(r1, r1, Operand(Heap::kArgumentsObjectSizeStrict / kPointerSize)); |
| 4782 | 4782 |
| 4783 // Do the allocation of both objects in one go. | 4783 // Do the allocation of both objects in one go. |
| 4784 __ AllocateInNewSpace(r1, | 4784 __ AllocateInNewSpace(r1, |
| 4785 r0, | 4785 r0, |
| 4786 r2, | 4786 r2, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 4799 __ CopyFields(r0, r4, r3.bit(), JSObject::kHeaderSize / kPointerSize); | 4799 __ CopyFields(r0, r4, r3.bit(), JSObject::kHeaderSize / kPointerSize); |
| 4800 | 4800 |
| 4801 // Get the length (smi tagged) and set that as an in-object property too. | 4801 // Get the length (smi tagged) and set that as an in-object property too. |
| 4802 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); | 4802 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); |
| 4803 __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); | 4803 __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); |
| 4804 __ str(r1, FieldMemOperand(r0, JSObject::kHeaderSize + | 4804 __ str(r1, FieldMemOperand(r0, JSObject::kHeaderSize + |
| 4805 Heap::kArgumentsLengthIndex * kPointerSize)); | 4805 Heap::kArgumentsLengthIndex * kPointerSize)); |
| 4806 | 4806 |
| 4807 // If there are no actual arguments, we're done. | 4807 // If there are no actual arguments, we're done. |
| 4808 Label done; | 4808 Label done; |
| 4809 __ cmp(r1, Operand(0, RelocInfo::NONE)); | 4809 __ cmp(r1, Operand(0, RelocInfo::NONE32)); |
| 4810 __ b(eq, &done); | 4810 __ b(eq, &done); |
| 4811 | 4811 |
| 4812 // Get the parameters pointer from the stack. | 4812 // Get the parameters pointer from the stack. |
| 4813 __ ldr(r2, MemOperand(sp, 1 * kPointerSize)); | 4813 __ ldr(r2, MemOperand(sp, 1 * kPointerSize)); |
| 4814 | 4814 |
| 4815 // Set up the elements pointer in the allocated arguments object and | 4815 // Set up the elements pointer in the allocated arguments object and |
| 4816 // initialize the header in the elements fixed array. | 4816 // initialize the header in the elements fixed array. |
| 4817 __ add(r4, r0, Operand(Heap::kArgumentsObjectSizeStrict)); | 4817 __ add(r4, r0, Operand(Heap::kArgumentsObjectSizeStrict)); |
| 4818 __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); | 4818 __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); |
| 4819 __ LoadRoot(r3, Heap::kFixedArrayMapRootIndex); | 4819 __ LoadRoot(r3, Heap::kFixedArrayMapRootIndex); |
| 4820 __ str(r3, FieldMemOperand(r4, FixedArray::kMapOffset)); | 4820 __ str(r3, FieldMemOperand(r4, FixedArray::kMapOffset)); |
| 4821 __ str(r1, FieldMemOperand(r4, FixedArray::kLengthOffset)); | 4821 __ str(r1, FieldMemOperand(r4, FixedArray::kLengthOffset)); |
| 4822 // Untag the length for the loop. | 4822 // Untag the length for the loop. |
| 4823 __ mov(r1, Operand(r1, LSR, kSmiTagSize)); | 4823 __ mov(r1, Operand(r1, LSR, kSmiTagSize)); |
| 4824 | 4824 |
| 4825 // Copy the fixed array slots. | 4825 // Copy the fixed array slots. |
| 4826 Label loop; | 4826 Label loop; |
| 4827 // Set up r4 to point to the first array slot. | 4827 // Set up r4 to point to the first array slot. |
| 4828 __ add(r4, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 4828 __ add(r4, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 4829 __ bind(&loop); | 4829 __ bind(&loop); |
| 4830 // Pre-decrement r2 with kPointerSize on each iteration. | 4830 // Pre-decrement r2 with kPointerSize on each iteration. |
| 4831 // Pre-decrement in order to skip receiver. | 4831 // Pre-decrement in order to skip receiver. |
| 4832 __ ldr(r3, MemOperand(r2, kPointerSize, NegPreIndex)); | 4832 __ ldr(r3, MemOperand(r2, kPointerSize, NegPreIndex)); |
| 4833 // Post-increment r4 with kPointerSize on each iteration. | 4833 // Post-increment r4 with kPointerSize on each iteration. |
| 4834 __ str(r3, MemOperand(r4, kPointerSize, PostIndex)); | 4834 __ str(r3, MemOperand(r4, kPointerSize, PostIndex)); |
| 4835 __ sub(r1, r1, Operand(1)); | 4835 __ sub(r1, r1, Operand(1)); |
| 4836 __ cmp(r1, Operand(0, RelocInfo::NONE)); | 4836 __ cmp(r1, Operand(0, RelocInfo::NONE32)); |
| 4837 __ b(ne, &loop); | 4837 __ b(ne, &loop); |
| 4838 | 4838 |
| 4839 // Return and remove the on-stack parameters. | 4839 // Return and remove the on-stack parameters. |
| 4840 __ bind(&done); | 4840 __ bind(&done); |
| 4841 __ add(sp, sp, Operand(3 * kPointerSize)); | 4841 __ add(sp, sp, Operand(3 * kPointerSize)); |
| 4842 __ Ret(); | 4842 __ Ret(); |
| 4843 | 4843 |
| 4844 // Do the runtime call to allocate the arguments object. | 4844 // Do the runtime call to allocate the arguments object. |
| 4845 __ bind(&runtime); | 4845 __ bind(&runtime); |
| 4846 __ TailCallRuntime(Runtime::kNewStrictArgumentsFast, 3, 1); | 4846 __ TailCallRuntime(Runtime::kNewStrictArgumentsFast, 3, 1); |
| (...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5462 // object (undefined) so no write barrier is needed. | 5462 // object (undefined) so no write barrier is needed. |
| 5463 ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()), | 5463 ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()), |
| 5464 masm->isolate()->heap()->undefined_value()); | 5464 masm->isolate()->heap()->undefined_value()); |
| 5465 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 5465 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 5466 __ str(ip, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset)); | 5466 __ str(ip, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset)); |
| 5467 } | 5467 } |
| 5468 // Check for function proxy. | 5468 // Check for function proxy. |
| 5469 __ cmp(r3, Operand(JS_FUNCTION_PROXY_TYPE)); | 5469 __ cmp(r3, Operand(JS_FUNCTION_PROXY_TYPE)); |
| 5470 __ b(ne, &non_function); | 5470 __ b(ne, &non_function); |
| 5471 __ push(r1); // put proxy as additional argument | 5471 __ push(r1); // put proxy as additional argument |
| 5472 __ mov(r0, Operand(argc_ + 1, RelocInfo::NONE)); | 5472 __ mov(r0, Operand(argc_ + 1, RelocInfo::NONE32)); |
| 5473 __ mov(r2, Operand(0, RelocInfo::NONE)); | 5473 __ mov(r2, Operand(0, RelocInfo::NONE32)); |
| 5474 __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY); | 5474 __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY); |
| 5475 __ SetCallKind(r5, CALL_AS_METHOD); | 5475 __ SetCallKind(r5, CALL_AS_METHOD); |
| 5476 { | 5476 { |
| 5477 Handle<Code> adaptor = | 5477 Handle<Code> adaptor = |
| 5478 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); | 5478 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); |
| 5479 __ Jump(adaptor, RelocInfo::CODE_TARGET); | 5479 __ Jump(adaptor, RelocInfo::CODE_TARGET); |
| 5480 } | 5480 } |
| 5481 | 5481 |
| 5482 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead | 5482 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead |
| 5483 // of the original receiver from the call site). | 5483 // of the original receiver from the call site). |
| 5484 __ bind(&non_function); | 5484 __ bind(&non_function); |
| 5485 __ str(r1, MemOperand(sp, argc_ * kPointerSize)); | 5485 __ str(r1, MemOperand(sp, argc_ * kPointerSize)); |
| 5486 __ mov(r0, Operand(argc_)); // Set up the number of arguments. | 5486 __ mov(r0, Operand(argc_)); // Set up the number of arguments. |
| 5487 __ mov(r2, Operand(0, RelocInfo::NONE)); | 5487 __ mov(r2, Operand(0, RelocInfo::NONE32)); |
| 5488 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); | 5488 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); |
| 5489 __ SetCallKind(r5, CALL_AS_METHOD); | 5489 __ SetCallKind(r5, CALL_AS_METHOD); |
| 5490 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 5490 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
| 5491 RelocInfo::CODE_TARGET); | 5491 RelocInfo::CODE_TARGET); |
| 5492 } | 5492 } |
| 5493 | 5493 |
| 5494 | 5494 |
| 5495 void CallConstructStub::Generate(MacroAssembler* masm) { | 5495 void CallConstructStub::Generate(MacroAssembler* masm) { |
| 5496 // r0 : number of arguments | 5496 // r0 : number of arguments |
| 5497 // r1 : the function to call | 5497 // r1 : the function to call |
| (...skipping 22 matching lines...) Expand all Loading... |
| 5520 __ bind(&slow); | 5520 __ bind(&slow); |
| 5521 __ cmp(r3, Operand(JS_FUNCTION_PROXY_TYPE)); | 5521 __ cmp(r3, Operand(JS_FUNCTION_PROXY_TYPE)); |
| 5522 __ b(ne, &non_function_call); | 5522 __ b(ne, &non_function_call); |
| 5523 __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); | 5523 __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); |
| 5524 __ jmp(&do_call); | 5524 __ jmp(&do_call); |
| 5525 | 5525 |
| 5526 __ bind(&non_function_call); | 5526 __ bind(&non_function_call); |
| 5527 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); | 5527 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); |
| 5528 __ bind(&do_call); | 5528 __ bind(&do_call); |
| 5529 // Set expected number of arguments to zero (not changing r0). | 5529 // Set expected number of arguments to zero (not changing r0). |
| 5530 __ mov(r2, Operand(0, RelocInfo::NONE)); | 5530 __ mov(r2, Operand(0, RelocInfo::NONE32)); |
| 5531 __ SetCallKind(r5, CALL_AS_METHOD); | 5531 __ SetCallKind(r5, CALL_AS_METHOD); |
| 5532 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 5532 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
| 5533 RelocInfo::CODE_TARGET); | 5533 RelocInfo::CODE_TARGET); |
| 5534 } | 5534 } |
| 5535 | 5535 |
| 5536 | 5536 |
| 5537 // StringCharCodeAtGenerator | 5537 // StringCharCodeAtGenerator |
| 5538 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { | 5538 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { |
| 5539 Label flat_string; | 5539 Label flat_string; |
| 5540 Label ascii_string; | 5540 Label ascii_string; |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5689 Register count, | 5689 Register count, |
| 5690 Register scratch, | 5690 Register scratch, |
| 5691 bool ascii) { | 5691 bool ascii) { |
| 5692 Label loop; | 5692 Label loop; |
| 5693 Label done; | 5693 Label done; |
| 5694 // This loop just copies one character at a time, as it is only used for very | 5694 // This loop just copies one character at a time, as it is only used for very |
| 5695 // short strings. | 5695 // short strings. |
| 5696 if (!ascii) { | 5696 if (!ascii) { |
| 5697 __ add(count, count, Operand(count), SetCC); | 5697 __ add(count, count, Operand(count), SetCC); |
| 5698 } else { | 5698 } else { |
| 5699 __ cmp(count, Operand(0, RelocInfo::NONE)); | 5699 __ cmp(count, Operand(0, RelocInfo::NONE32)); |
| 5700 } | 5700 } |
| 5701 __ b(eq, &done); | 5701 __ b(eq, &done); |
| 5702 | 5702 |
| 5703 __ bind(&loop); | 5703 __ bind(&loop); |
| 5704 __ ldrb(scratch, MemOperand(src, 1, PostIndex)); | 5704 __ ldrb(scratch, MemOperand(src, 1, PostIndex)); |
| 5705 // Perform sub between load and dependent store to get the load time to | 5705 // Perform sub between load and dependent store to get the load time to |
| 5706 // complete. | 5706 // complete. |
| 5707 __ sub(count, count, Operand(1), SetCC); | 5707 __ sub(count, count, Operand(1), SetCC); |
| 5708 __ strb(scratch, MemOperand(dest, 1, PostIndex)); | 5708 __ strb(scratch, MemOperand(dest, 1, PostIndex)); |
| 5709 // last iteration. | 5709 // last iteration. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5744 // Ensure that reading an entire aligned word containing the last character | 5744 // Ensure that reading an entire aligned word containing the last character |
| 5745 // of a string will not read outside the allocated area (because we pad up | 5745 // of a string will not read outside the allocated area (because we pad up |
| 5746 // to kObjectAlignment). | 5746 // to kObjectAlignment). |
| 5747 STATIC_ASSERT(kObjectAlignment >= kReadAlignment); | 5747 STATIC_ASSERT(kObjectAlignment >= kReadAlignment); |
| 5748 // Assumes word reads and writes are little endian. | 5748 // Assumes word reads and writes are little endian. |
| 5749 // Nothing to do for zero characters. | 5749 // Nothing to do for zero characters. |
| 5750 Label done; | 5750 Label done; |
| 5751 if (!ascii) { | 5751 if (!ascii) { |
| 5752 __ add(count, count, Operand(count), SetCC); | 5752 __ add(count, count, Operand(count), SetCC); |
| 5753 } else { | 5753 } else { |
| 5754 __ cmp(count, Operand(0, RelocInfo::NONE)); | 5754 __ cmp(count, Operand(0, RelocInfo::NONE32)); |
| 5755 } | 5755 } |
| 5756 __ b(eq, &done); | 5756 __ b(eq, &done); |
| 5757 | 5757 |
| 5758 // Assume that you cannot read (or write) unaligned. | 5758 // Assume that you cannot read (or write) unaligned. |
| 5759 Label byte_loop; | 5759 Label byte_loop; |
| 5760 // Must copy at least eight bytes, otherwise just do it one byte at a time. | 5760 // Must copy at least eight bytes, otherwise just do it one byte at a time. |
| 5761 __ cmp(count, Operand(8)); | 5761 __ cmp(count, Operand(8)); |
| 5762 __ add(count, dest, Operand(count)); | 5762 __ add(count, dest, Operand(count)); |
| 5763 Register limit = count; // Read until src equals this. | 5763 Register limit = count; // Read until src equals this. |
| 5764 __ b(lt, &byte_loop); | 5764 __ b(lt, &byte_loop); |
| (...skipping 1945 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7710 | 7710 |
| 7711 __ Pop(lr, r5, r1); | 7711 __ Pop(lr, r5, r1); |
| 7712 __ Ret(); | 7712 __ Ret(); |
| 7713 } | 7713 } |
| 7714 | 7714 |
| 7715 #undef __ | 7715 #undef __ |
| 7716 | 7716 |
| 7717 } } // namespace v8::internal | 7717 } } // namespace v8::internal |
| 7718 | 7718 |
| 7719 #endif // V8_TARGET_ARCH_ARM | 7719 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |