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 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 Condition cc, | 269 Condition cc, |
270 Label* branch, | 270 Label* branch, |
271 Label::Distance distance) { | 271 Label::Distance distance) { |
272 if (Serializer::enabled()) { | 272 if (Serializer::enabled()) { |
273 // Can't do arithmetic on external references if it might get serialized. | 273 // Can't do arithmetic on external references if it might get serialized. |
274 // The mask isn't really an address. We load it as an external reference in | 274 // The mask isn't really an address. We load it as an external reference in |
275 // case the size of the new space is different between the snapshot maker | 275 // case the size of the new space is different between the snapshot maker |
276 // and the running system. | 276 // and the running system. |
277 if (scratch.is(object)) { | 277 if (scratch.is(object)) { |
278 Move(kScratchRegister, ExternalReference::new_space_mask(isolate())); | 278 Move(kScratchRegister, ExternalReference::new_space_mask(isolate())); |
279 and_(scratch, kScratchRegister); | 279 andp(scratch, kScratchRegister); |
280 } else { | 280 } else { |
281 Move(scratch, ExternalReference::new_space_mask(isolate())); | 281 Move(scratch, ExternalReference::new_space_mask(isolate())); |
282 and_(scratch, object); | 282 andp(scratch, object); |
283 } | 283 } |
284 Move(kScratchRegister, ExternalReference::new_space_start(isolate())); | 284 Move(kScratchRegister, ExternalReference::new_space_start(isolate())); |
285 cmpp(scratch, kScratchRegister); | 285 cmpp(scratch, kScratchRegister); |
286 j(cc, branch, distance); | 286 j(cc, branch, distance); |
287 } else { | 287 } else { |
288 ASSERT(is_int32(static_cast<int64_t>(isolate()->heap()->NewSpaceMask()))); | 288 ASSERT(is_int32(static_cast<int64_t>(isolate()->heap()->NewSpaceMask()))); |
289 intptr_t new_space_start = | 289 intptr_t new_space_start = |
290 reinterpret_cast<intptr_t>(isolate()->heap()->NewSpaceStart()); | 290 reinterpret_cast<intptr_t>(isolate()->heap()->NewSpaceStart()); |
291 Move(kScratchRegister, reinterpret_cast<Address>(-new_space_start), | 291 Move(kScratchRegister, reinterpret_cast<Address>(-new_space_start), |
292 Assembler::RelocInfoNone()); | 292 Assembler::RelocInfoNone()); |
293 if (scratch.is(object)) { | 293 if (scratch.is(object)) { |
294 addp(scratch, kScratchRegister); | 294 addp(scratch, kScratchRegister); |
295 } else { | 295 } else { |
296 leap(scratch, Operand(object, kScratchRegister, times_1, 0)); | 296 leap(scratch, Operand(object, kScratchRegister, times_1, 0)); |
297 } | 297 } |
298 and_(scratch, | 298 andp(scratch, |
299 Immediate(static_cast<int32_t>(isolate()->heap()->NewSpaceMask()))); | 299 Immediate(static_cast<int32_t>(isolate()->heap()->NewSpaceMask()))); |
300 j(cc, branch, distance); | 300 j(cc, branch, distance); |
301 } | 301 } |
302 } | 302 } |
303 | 303 |
304 | 304 |
305 void MacroAssembler::RecordWriteField( | 305 void MacroAssembler::RecordWriteField( |
306 Register object, | 306 Register object, |
307 int offset, | 307 int offset, |
308 Register value, | 308 Register value, |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
569 void MacroAssembler::IndexFromHash(Register hash, Register index) { | 569 void MacroAssembler::IndexFromHash(Register hash, Register index) { |
570 // The assert checks that the constants for the maximum number of digits | 570 // The assert checks that the constants for the maximum number of digits |
571 // for an array index cached in the hash field and the number of bits | 571 // for an array index cached in the hash field and the number of bits |
572 // reserved for it does not conflict. | 572 // reserved for it does not conflict. |
573 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < | 573 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < |
574 (1 << String::kArrayIndexValueBits)); | 574 (1 << String::kArrayIndexValueBits)); |
575 // We want the smi-tagged index in key. Even if we subsequently go to | 575 // We want the smi-tagged index in key. Even if we subsequently go to |
576 // the slow case, converting the key to a smi is always valid. | 576 // the slow case, converting the key to a smi is always valid. |
577 // key: string key | 577 // key: string key |
578 // hash: key's hash field, including its array index value. | 578 // hash: key's hash field, including its array index value. |
579 and_(hash, Immediate(String::kArrayIndexValueMask)); | 579 andp(hash, Immediate(String::kArrayIndexValueMask)); |
580 shr(hash, Immediate(String::kHashShift)); | 580 shr(hash, Immediate(String::kHashShift)); |
581 // Here we actually clobber the key which will be used if calling into | 581 // Here we actually clobber the key which will be used if calling into |
582 // runtime later. However as the new key is the numeric value of a string key | 582 // runtime later. However as the new key is the numeric value of a string key |
583 // there is no difference in using either key. | 583 // there is no difference in using either key. |
584 Integer32ToSmi(index, hash); | 584 Integer32ToSmi(index, hash); |
585 } | 585 } |
586 | 586 |
587 | 587 |
588 void MacroAssembler::CallRuntime(const Runtime::Function* f, | 588 void MacroAssembler::CallRuntime(const Runtime::Function* f, |
589 int num_arguments, | 589 int num_arguments, |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
995 return !is_intn(x, kMaxBits); | 995 return !is_intn(x, kMaxBits); |
996 } | 996 } |
997 | 997 |
998 | 998 |
999 void MacroAssembler::SafeMove(Register dst, Smi* src) { | 999 void MacroAssembler::SafeMove(Register dst, Smi* src) { |
1000 ASSERT(!dst.is(kScratchRegister)); | 1000 ASSERT(!dst.is(kScratchRegister)); |
1001 ASSERT(SmiValuesAre32Bits()); // JIT cookie can be converted to Smi. | 1001 ASSERT(SmiValuesAre32Bits()); // JIT cookie can be converted to Smi. |
1002 if (IsUnsafeInt(src->value()) && jit_cookie() != 0) { | 1002 if (IsUnsafeInt(src->value()) && jit_cookie() != 0) { |
1003 Move(dst, Smi::FromInt(src->value() ^ jit_cookie())); | 1003 Move(dst, Smi::FromInt(src->value() ^ jit_cookie())); |
1004 Move(kScratchRegister, Smi::FromInt(jit_cookie())); | 1004 Move(kScratchRegister, Smi::FromInt(jit_cookie())); |
1005 xor_(dst, kScratchRegister); | 1005 xorq(dst, kScratchRegister); |
1006 } else { | 1006 } else { |
1007 Move(dst, src); | 1007 Move(dst, src); |
1008 } | 1008 } |
1009 } | 1009 } |
1010 | 1010 |
1011 | 1011 |
1012 void MacroAssembler::SafePush(Smi* src) { | 1012 void MacroAssembler::SafePush(Smi* src) { |
1013 ASSERT(SmiValuesAre32Bits()); // JIT cookie can be converted to Smi. | 1013 ASSERT(SmiValuesAre32Bits()); // JIT cookie can be converted to Smi. |
1014 if (IsUnsafeInt(src->value()) && jit_cookie() != 0) { | 1014 if (IsUnsafeInt(src->value()) && jit_cookie() != 0) { |
1015 Push(Smi::FromInt(src->value() ^ jit_cookie())); | 1015 Push(Smi::FromInt(src->value() ^ jit_cookie())); |
1016 Move(kScratchRegister, Smi::FromInt(jit_cookie())); | 1016 Move(kScratchRegister, Smi::FromInt(jit_cookie())); |
1017 xor_(Operand(rsp, 0), kScratchRegister); | 1017 xorq(Operand(rsp, 0), kScratchRegister); |
1018 } else { | 1018 } else { |
1019 Push(src); | 1019 Push(src); |
1020 } | 1020 } |
1021 } | 1021 } |
1022 | 1022 |
1023 | 1023 |
1024 Register MacroAssembler::GetSmiConstant(Smi* source) { | 1024 Register MacroAssembler::GetSmiConstant(Smi* source) { |
1025 int value = source->value(); | 1025 int value = source->value(); |
1026 if (value == 0) { | 1026 if (value == 0) { |
1027 xorl(kScratchRegister, kScratchRegister); | 1027 xorl(kScratchRegister, kScratchRegister); |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1248 } | 1248 } |
1249 | 1249 |
1250 | 1250 |
1251 void MacroAssembler::SmiOrIfSmis(Register dst, Register src1, Register src2, | 1251 void MacroAssembler::SmiOrIfSmis(Register dst, Register src1, Register src2, |
1252 Label* on_not_smis, | 1252 Label* on_not_smis, |
1253 Label::Distance near_jump) { | 1253 Label::Distance near_jump) { |
1254 if (dst.is(src1) || dst.is(src2)) { | 1254 if (dst.is(src1) || dst.is(src2)) { |
1255 ASSERT(!src1.is(kScratchRegister)); | 1255 ASSERT(!src1.is(kScratchRegister)); |
1256 ASSERT(!src2.is(kScratchRegister)); | 1256 ASSERT(!src2.is(kScratchRegister)); |
1257 movp(kScratchRegister, src1); | 1257 movp(kScratchRegister, src1); |
1258 or_(kScratchRegister, src2); | 1258 orp(kScratchRegister, src2); |
1259 JumpIfNotSmi(kScratchRegister, on_not_smis, near_jump); | 1259 JumpIfNotSmi(kScratchRegister, on_not_smis, near_jump); |
1260 movp(dst, kScratchRegister); | 1260 movp(dst, kScratchRegister); |
1261 } else { | 1261 } else { |
1262 movp(dst, src1); | 1262 movp(dst, src1); |
1263 or_(dst, src2); | 1263 orp(dst, src2); |
1264 JumpIfNotSmi(dst, on_not_smis, near_jump); | 1264 JumpIfNotSmi(dst, on_not_smis, near_jump); |
1265 } | 1265 } |
1266 } | 1266 } |
1267 | 1267 |
1268 | 1268 |
1269 Condition MacroAssembler::CheckSmi(Register src) { | 1269 Condition MacroAssembler::CheckSmi(Register src) { |
1270 STATIC_ASSERT(kSmiTag == 0); | 1270 STATIC_ASSERT(kSmiTag == 0); |
1271 testb(src, Immediate(kSmiTagMask)); | 1271 testb(src, Immediate(kSmiTagMask)); |
1272 return zero; | 1272 return zero; |
1273 } | 1273 } |
(...skipping 26 matching lines...) Expand all Loading... |
1300 return zero; | 1300 return zero; |
1301 } | 1301 } |
1302 | 1302 |
1303 | 1303 |
1304 Condition MacroAssembler::CheckBothNonNegativeSmi(Register first, | 1304 Condition MacroAssembler::CheckBothNonNegativeSmi(Register first, |
1305 Register second) { | 1305 Register second) { |
1306 if (first.is(second)) { | 1306 if (first.is(second)) { |
1307 return CheckNonNegativeSmi(first); | 1307 return CheckNonNegativeSmi(first); |
1308 } | 1308 } |
1309 movp(kScratchRegister, first); | 1309 movp(kScratchRegister, first); |
1310 or_(kScratchRegister, second); | 1310 orp(kScratchRegister, second); |
1311 rol(kScratchRegister, Immediate(1)); | 1311 rol(kScratchRegister, Immediate(1)); |
1312 testl(kScratchRegister, Immediate(3)); | 1312 testl(kScratchRegister, Immediate(3)); |
1313 return zero; | 1313 return zero; |
1314 } | 1314 } |
1315 | 1315 |
1316 | 1316 |
1317 Condition MacroAssembler::CheckEitherSmi(Register first, | 1317 Condition MacroAssembler::CheckEitherSmi(Register first, |
1318 Register second, | 1318 Register second, |
1319 Register scratch) { | 1319 Register scratch) { |
1320 if (first.is(second)) { | 1320 if (first.is(second)) { |
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1792 imulp(dst, src2); | 1792 imulp(dst, src2); |
1793 j(overflow, &failure, Label::kNear); | 1793 j(overflow, &failure, Label::kNear); |
1794 | 1794 |
1795 // Check for negative zero result. If product is zero, and one | 1795 // Check for negative zero result. If product is zero, and one |
1796 // argument is negative, go to slow case. | 1796 // argument is negative, go to slow case. |
1797 Label correct_result; | 1797 Label correct_result; |
1798 testp(dst, dst); | 1798 testp(dst, dst); |
1799 j(not_zero, &correct_result, Label::kNear); | 1799 j(not_zero, &correct_result, Label::kNear); |
1800 | 1800 |
1801 movp(dst, kScratchRegister); | 1801 movp(dst, kScratchRegister); |
1802 xor_(dst, src2); | 1802 xorp(dst, src2); |
1803 // Result was positive zero. | 1803 // Result was positive zero. |
1804 j(positive, &zero_correct_result, Label::kNear); | 1804 j(positive, &zero_correct_result, Label::kNear); |
1805 | 1805 |
1806 bind(&failure); // Reused failure exit, restores src1. | 1806 bind(&failure); // Reused failure exit, restores src1. |
1807 movp(src1, kScratchRegister); | 1807 movp(src1, kScratchRegister); |
1808 jmp(on_not_smi_result, near_jump); | 1808 jmp(on_not_smi_result, near_jump); |
1809 | 1809 |
1810 bind(&zero_correct_result); | 1810 bind(&zero_correct_result); |
1811 Set(dst, 0); | 1811 Set(dst, 0); |
1812 | 1812 |
1813 bind(&correct_result); | 1813 bind(&correct_result); |
1814 } else { | 1814 } else { |
1815 SmiToInteger64(dst, src1); | 1815 SmiToInteger64(dst, src1); |
1816 imulp(dst, src2); | 1816 imulp(dst, src2); |
1817 j(overflow, on_not_smi_result, near_jump); | 1817 j(overflow, on_not_smi_result, near_jump); |
1818 // Check for negative zero result. If product is zero, and one | 1818 // Check for negative zero result. If product is zero, and one |
1819 // argument is negative, go to slow case. | 1819 // argument is negative, go to slow case. |
1820 Label correct_result; | 1820 Label correct_result; |
1821 testp(dst, dst); | 1821 testp(dst, dst); |
1822 j(not_zero, &correct_result, Label::kNear); | 1822 j(not_zero, &correct_result, Label::kNear); |
1823 // One of src1 and src2 is zero, the check whether the other is | 1823 // One of src1 and src2 is zero, the check whether the other is |
1824 // negative. | 1824 // negative. |
1825 movp(kScratchRegister, src1); | 1825 movp(kScratchRegister, src1); |
1826 xor_(kScratchRegister, src2); | 1826 xorp(kScratchRegister, src2); |
1827 j(negative, on_not_smi_result, near_jump); | 1827 j(negative, on_not_smi_result, near_jump); |
1828 bind(&correct_result); | 1828 bind(&correct_result); |
1829 } | 1829 } |
1830 } | 1830 } |
1831 | 1831 |
1832 | 1832 |
1833 void MacroAssembler::SmiDiv(Register dst, | 1833 void MacroAssembler::SmiDiv(Register dst, |
1834 Register src1, | 1834 Register src1, |
1835 Register src2, | 1835 Register src2, |
1836 Label* on_not_smi_result, | 1836 Label* on_not_smi_result, |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1948 Integer32ToSmi(dst, rdx); | 1948 Integer32ToSmi(dst, rdx); |
1949 } | 1949 } |
1950 | 1950 |
1951 | 1951 |
1952 void MacroAssembler::SmiNot(Register dst, Register src) { | 1952 void MacroAssembler::SmiNot(Register dst, Register src) { |
1953 ASSERT(!dst.is(kScratchRegister)); | 1953 ASSERT(!dst.is(kScratchRegister)); |
1954 ASSERT(!src.is(kScratchRegister)); | 1954 ASSERT(!src.is(kScratchRegister)); |
1955 // Set tag and padding bits before negating, so that they are zero afterwards. | 1955 // Set tag and padding bits before negating, so that they are zero afterwards. |
1956 movl(kScratchRegister, Immediate(~0)); | 1956 movl(kScratchRegister, Immediate(~0)); |
1957 if (dst.is(src)) { | 1957 if (dst.is(src)) { |
1958 xor_(dst, kScratchRegister); | 1958 xorp(dst, kScratchRegister); |
1959 } else { | 1959 } else { |
1960 leap(dst, Operand(src, kScratchRegister, times_1, 0)); | 1960 leap(dst, Operand(src, kScratchRegister, times_1, 0)); |
1961 } | 1961 } |
1962 not_(dst); | 1962 notp(dst); |
1963 } | 1963 } |
1964 | 1964 |
1965 | 1965 |
1966 void MacroAssembler::SmiAnd(Register dst, Register src1, Register src2) { | 1966 void MacroAssembler::SmiAnd(Register dst, Register src1, Register src2) { |
1967 ASSERT(!dst.is(src2)); | 1967 ASSERT(!dst.is(src2)); |
1968 if (!dst.is(src1)) { | 1968 if (!dst.is(src1)) { |
1969 movp(dst, src1); | 1969 movp(dst, src1); |
1970 } | 1970 } |
1971 and_(dst, src2); | 1971 andp(dst, src2); |
1972 } | 1972 } |
1973 | 1973 |
1974 | 1974 |
1975 void MacroAssembler::SmiAndConstant(Register dst, Register src, Smi* constant) { | 1975 void MacroAssembler::SmiAndConstant(Register dst, Register src, Smi* constant) { |
1976 if (constant->value() == 0) { | 1976 if (constant->value() == 0) { |
1977 Set(dst, 0); | 1977 Set(dst, 0); |
1978 } else if (dst.is(src)) { | 1978 } else if (dst.is(src)) { |
1979 ASSERT(!dst.is(kScratchRegister)); | 1979 ASSERT(!dst.is(kScratchRegister)); |
1980 Register constant_reg = GetSmiConstant(constant); | 1980 Register constant_reg = GetSmiConstant(constant); |
1981 and_(dst, constant_reg); | 1981 andp(dst, constant_reg); |
1982 } else { | 1982 } else { |
1983 LoadSmiConstant(dst, constant); | 1983 LoadSmiConstant(dst, constant); |
1984 and_(dst, src); | 1984 andp(dst, src); |
1985 } | 1985 } |
1986 } | 1986 } |
1987 | 1987 |
1988 | 1988 |
1989 void MacroAssembler::SmiOr(Register dst, Register src1, Register src2) { | 1989 void MacroAssembler::SmiOr(Register dst, Register src1, Register src2) { |
1990 if (!dst.is(src1)) { | 1990 if (!dst.is(src1)) { |
1991 ASSERT(!src1.is(src2)); | 1991 ASSERT(!src1.is(src2)); |
1992 movp(dst, src1); | 1992 movp(dst, src1); |
1993 } | 1993 } |
1994 or_(dst, src2); | 1994 orp(dst, src2); |
1995 } | 1995 } |
1996 | 1996 |
1997 | 1997 |
1998 void MacroAssembler::SmiOrConstant(Register dst, Register src, Smi* constant) { | 1998 void MacroAssembler::SmiOrConstant(Register dst, Register src, Smi* constant) { |
1999 if (dst.is(src)) { | 1999 if (dst.is(src)) { |
2000 ASSERT(!dst.is(kScratchRegister)); | 2000 ASSERT(!dst.is(kScratchRegister)); |
2001 Register constant_reg = GetSmiConstant(constant); | 2001 Register constant_reg = GetSmiConstant(constant); |
2002 or_(dst, constant_reg); | 2002 orp(dst, constant_reg); |
2003 } else { | 2003 } else { |
2004 LoadSmiConstant(dst, constant); | 2004 LoadSmiConstant(dst, constant); |
2005 or_(dst, src); | 2005 orp(dst, src); |
2006 } | 2006 } |
2007 } | 2007 } |
2008 | 2008 |
2009 | 2009 |
2010 void MacroAssembler::SmiXor(Register dst, Register src1, Register src2) { | 2010 void MacroAssembler::SmiXor(Register dst, Register src1, Register src2) { |
2011 if (!dst.is(src1)) { | 2011 if (!dst.is(src1)) { |
2012 ASSERT(!src1.is(src2)); | 2012 ASSERT(!src1.is(src2)); |
2013 movp(dst, src1); | 2013 movp(dst, src1); |
2014 } | 2014 } |
2015 xor_(dst, src2); | 2015 xorp(dst, src2); |
2016 } | 2016 } |
2017 | 2017 |
2018 | 2018 |
2019 void MacroAssembler::SmiXorConstant(Register dst, Register src, Smi* constant) { | 2019 void MacroAssembler::SmiXorConstant(Register dst, Register src, Smi* constant) { |
2020 if (dst.is(src)) { | 2020 if (dst.is(src)) { |
2021 ASSERT(!dst.is(kScratchRegister)); | 2021 ASSERT(!dst.is(kScratchRegister)); |
2022 Register constant_reg = GetSmiConstant(constant); | 2022 Register constant_reg = GetSmiConstant(constant); |
2023 xor_(dst, constant_reg); | 2023 xorp(dst, constant_reg); |
2024 } else { | 2024 } else { |
2025 LoadSmiConstant(dst, constant); | 2025 LoadSmiConstant(dst, constant); |
2026 xor_(dst, src); | 2026 xorp(dst, src); |
2027 } | 2027 } |
2028 } | 2028 } |
2029 | 2029 |
2030 | 2030 |
2031 void MacroAssembler::SmiShiftArithmeticRightConstant(Register dst, | 2031 void MacroAssembler::SmiShiftArithmeticRightConstant(Register dst, |
2032 Register src, | 2032 Register src, |
2033 int shift_value) { | 2033 int shift_value) { |
2034 ASSERT(is_uint5(shift_value)); | 2034 ASSERT(is_uint5(shift_value)); |
2035 if (shift_value > 0) { | 2035 if (shift_value > 0) { |
2036 if (dst.is(src)) { | 2036 if (dst.is(src)) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2076 void MacroAssembler::SmiShiftLeft(Register dst, | 2076 void MacroAssembler::SmiShiftLeft(Register dst, |
2077 Register src1, | 2077 Register src1, |
2078 Register src2) { | 2078 Register src2) { |
2079 ASSERT(!dst.is(rcx)); | 2079 ASSERT(!dst.is(rcx)); |
2080 // Untag shift amount. | 2080 // Untag shift amount. |
2081 if (!dst.is(src1)) { | 2081 if (!dst.is(src1)) { |
2082 movq(dst, src1); | 2082 movq(dst, src1); |
2083 } | 2083 } |
2084 SmiToInteger32(rcx, src2); | 2084 SmiToInteger32(rcx, src2); |
2085 // Shift amount specified by lower 5 bits, not six as the shl opcode. | 2085 // Shift amount specified by lower 5 bits, not six as the shl opcode. |
2086 and_(rcx, Immediate(0x1f)); | 2086 andq(rcx, Immediate(0x1f)); |
2087 shl_cl(dst); | 2087 shl_cl(dst); |
2088 } | 2088 } |
2089 | 2089 |
2090 | 2090 |
2091 void MacroAssembler::SmiShiftLogicalRight(Register dst, | 2091 void MacroAssembler::SmiShiftLogicalRight(Register dst, |
2092 Register src1, | 2092 Register src1, |
2093 Register src2, | 2093 Register src2, |
2094 Label* on_not_smi_result, | 2094 Label* on_not_smi_result, |
2095 Label::Distance near_jump) { | 2095 Label::Distance near_jump) { |
2096 ASSERT(!dst.is(kScratchRegister)); | 2096 ASSERT(!dst.is(kScratchRegister)); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2165 ASSERT(!dst.is(src1)); | 2165 ASSERT(!dst.is(src1)); |
2166 ASSERT(!dst.is(src2)); | 2166 ASSERT(!dst.is(src2)); |
2167 // Both operands must not be smis. | 2167 // Both operands must not be smis. |
2168 #ifdef DEBUG | 2168 #ifdef DEBUG |
2169 Condition not_both_smis = NegateCondition(CheckBothSmi(src1, src2)); | 2169 Condition not_both_smis = NegateCondition(CheckBothSmi(src1, src2)); |
2170 Check(not_both_smis, kBothRegistersWereSmisInSelectNonSmi); | 2170 Check(not_both_smis, kBothRegistersWereSmisInSelectNonSmi); |
2171 #endif | 2171 #endif |
2172 STATIC_ASSERT(kSmiTag == 0); | 2172 STATIC_ASSERT(kSmiTag == 0); |
2173 ASSERT_EQ(0, Smi::FromInt(0)); | 2173 ASSERT_EQ(0, Smi::FromInt(0)); |
2174 movl(kScratchRegister, Immediate(kSmiTagMask)); | 2174 movl(kScratchRegister, Immediate(kSmiTagMask)); |
2175 and_(kScratchRegister, src1); | 2175 andp(kScratchRegister, src1); |
2176 testl(kScratchRegister, src2); | 2176 testl(kScratchRegister, src2); |
2177 // If non-zero then both are smis. | 2177 // If non-zero then both are smis. |
2178 j(not_zero, on_not_smis, near_jump); | 2178 j(not_zero, on_not_smis, near_jump); |
2179 | 2179 |
2180 // Exactly one operand is a smi. | 2180 // Exactly one operand is a smi. |
2181 ASSERT_EQ(1, static_cast<int>(kSmiTagMask)); | 2181 ASSERT_EQ(1, static_cast<int>(kSmiTagMask)); |
2182 // kScratchRegister still holds src1 & kSmiTag, which is either zero or one. | 2182 // kScratchRegister still holds src1 & kSmiTag, which is either zero or one. |
2183 subp(kScratchRegister, Immediate(1)); | 2183 subp(kScratchRegister, Immediate(1)); |
2184 // If src1 is a smi, then scratch register all 1s, else it is all 0s. | 2184 // If src1 is a smi, then scratch register all 1s, else it is all 0s. |
2185 movp(dst, src1); | 2185 movp(dst, src1); |
2186 xor_(dst, src2); | 2186 xorp(dst, src2); |
2187 and_(dst, kScratchRegister); | 2187 andp(dst, kScratchRegister); |
2188 // If src1 is a smi, dst holds src1 ^ src2, else it is zero. | 2188 // If src1 is a smi, dst holds src1 ^ src2, else it is zero. |
2189 xor_(dst, src1); | 2189 xorp(dst, src1); |
2190 // If src1 is a smi, dst is src2, else it is src1, i.e., the non-smi. | 2190 // If src1 is a smi, dst is src2, else it is src1, i.e., the non-smi. |
2191 } | 2191 } |
2192 | 2192 |
2193 | 2193 |
2194 SmiIndex MacroAssembler::SmiToIndex(Register dst, | 2194 SmiIndex MacroAssembler::SmiToIndex(Register dst, |
2195 Register src, | 2195 Register src, |
2196 int shift) { | 2196 int shift) { |
2197 ASSERT(is_uint6(shift)); | 2197 ASSERT(is_uint6(shift)); |
2198 // There is a possible optimization if shift is in the range 60-63, but that | 2198 // There is a possible optimization if shift is in the range 60-63, but that |
2199 // will (and must) never happen. | 2199 // will (and must) never happen. |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2256 | 2256 |
2257 | 2257 |
2258 void MacroAssembler::PopInt64AsTwoSmis(Register dst, Register scratch) { | 2258 void MacroAssembler::PopInt64AsTwoSmis(Register dst, Register scratch) { |
2259 Pop(scratch); | 2259 Pop(scratch); |
2260 // Low bits. | 2260 // Low bits. |
2261 shr(scratch, Immediate(kSmiShift)); | 2261 shr(scratch, Immediate(kSmiShift)); |
2262 Pop(dst); | 2262 Pop(dst); |
2263 shr(dst, Immediate(kSmiShift)); | 2263 shr(dst, Immediate(kSmiShift)); |
2264 // High bits. | 2264 // High bits. |
2265 shl(dst, Immediate(64 - kSmiShift)); | 2265 shl(dst, Immediate(64 - kSmiShift)); |
2266 or_(dst, scratch); | 2266 orp(dst, scratch); |
2267 } | 2267 } |
2268 | 2268 |
2269 | 2269 |
2270 void MacroAssembler::Test(const Operand& src, Smi* source) { | 2270 void MacroAssembler::Test(const Operand& src, Smi* source) { |
2271 testl(Operand(src, kIntSize), Immediate(source->value())); | 2271 testl(Operand(src, kIntSize), Immediate(source->value())); |
2272 } | 2272 } |
2273 | 2273 |
2274 | 2274 |
2275 // ---------------------------------------------------------------------------- | 2275 // ---------------------------------------------------------------------------- |
2276 | 2276 |
(...skipping 25 matching lines...) Expand all Loading... |
2302 Label is_smi; | 2302 Label is_smi; |
2303 Label load_result_from_cache; | 2303 Label load_result_from_cache; |
2304 JumpIfSmi(object, &is_smi); | 2304 JumpIfSmi(object, &is_smi); |
2305 CheckMap(object, | 2305 CheckMap(object, |
2306 isolate()->factory()->heap_number_map(), | 2306 isolate()->factory()->heap_number_map(), |
2307 not_found, | 2307 not_found, |
2308 DONT_DO_SMI_CHECK); | 2308 DONT_DO_SMI_CHECK); |
2309 | 2309 |
2310 STATIC_ASSERT(8 == kDoubleSize); | 2310 STATIC_ASSERT(8 == kDoubleSize); |
2311 movl(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4)); | 2311 movl(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4)); |
2312 xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset)); | 2312 xorp(scratch, FieldOperand(object, HeapNumber::kValueOffset)); |
2313 and_(scratch, mask); | 2313 andp(scratch, mask); |
2314 // Each entry in string cache consists of two pointer sized fields, | 2314 // Each entry in string cache consists of two pointer sized fields, |
2315 // but times_twice_pointer_size (multiplication by 16) scale factor | 2315 // but times_twice_pointer_size (multiplication by 16) scale factor |
2316 // is not supported by addrmode on x64 platform. | 2316 // is not supported by addrmode on x64 platform. |
2317 // So we have to premultiply entry index before lookup. | 2317 // So we have to premultiply entry index before lookup. |
2318 shl(scratch, Immediate(kPointerSizeLog2 + 1)); | 2318 shl(scratch, Immediate(kPointerSizeLog2 + 1)); |
2319 | 2319 |
2320 Register index = scratch; | 2320 Register index = scratch; |
2321 Register probe = mask; | 2321 Register probe = mask; |
2322 movp(probe, | 2322 movp(probe, |
2323 FieldOperand(number_string_cache, | 2323 FieldOperand(number_string_cache, |
2324 index, | 2324 index, |
2325 times_1, | 2325 times_1, |
2326 FixedArray::kHeaderSize)); | 2326 FixedArray::kHeaderSize)); |
2327 JumpIfSmi(probe, not_found); | 2327 JumpIfSmi(probe, not_found); |
2328 movsd(xmm0, FieldOperand(object, HeapNumber::kValueOffset)); | 2328 movsd(xmm0, FieldOperand(object, HeapNumber::kValueOffset)); |
2329 ucomisd(xmm0, FieldOperand(probe, HeapNumber::kValueOffset)); | 2329 ucomisd(xmm0, FieldOperand(probe, HeapNumber::kValueOffset)); |
2330 j(parity_even, not_found); // Bail out if NaN is involved. | 2330 j(parity_even, not_found); // Bail out if NaN is involved. |
2331 j(not_equal, not_found); // The cache did not contain this value. | 2331 j(not_equal, not_found); // The cache did not contain this value. |
2332 jmp(&load_result_from_cache); | 2332 jmp(&load_result_from_cache); |
2333 | 2333 |
2334 bind(&is_smi); | 2334 bind(&is_smi); |
2335 SmiToInteger32(scratch, object); | 2335 SmiToInteger32(scratch, object); |
2336 and_(scratch, mask); | 2336 andp(scratch, mask); |
2337 // Each entry in string cache consists of two pointer sized fields, | 2337 // Each entry in string cache consists of two pointer sized fields, |
2338 // but times_twice_pointer_size (multiplication by 16) scale factor | 2338 // but times_twice_pointer_size (multiplication by 16) scale factor |
2339 // is not supported by addrmode on x64 platform. | 2339 // is not supported by addrmode on x64 platform. |
2340 // So we have to premultiply entry index before lookup. | 2340 // So we have to premultiply entry index before lookup. |
2341 shl(scratch, Immediate(kPointerSizeLog2 + 1)); | 2341 shl(scratch, Immediate(kPointerSizeLog2 + 1)); |
2342 | 2342 |
2343 // Check if the entry is the smi we are looking for. | 2343 // Check if the entry is the smi we are looking for. |
2344 cmpp(object, | 2344 cmpp(object, |
2345 FieldOperand(number_string_cache, | 2345 FieldOperand(number_string_cache, |
2346 index, | 2346 index, |
(...skipping 987 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3334 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) { | 3334 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) { |
3335 movp(dst, FieldOperand(map, Map::kBitField3Offset)); | 3335 movp(dst, FieldOperand(map, Map::kBitField3Offset)); |
3336 DecodeField<Map::NumberOfOwnDescriptorsBits>(dst); | 3336 DecodeField<Map::NumberOfOwnDescriptorsBits>(dst); |
3337 } | 3337 } |
3338 | 3338 |
3339 | 3339 |
3340 void MacroAssembler::EnumLength(Register dst, Register map) { | 3340 void MacroAssembler::EnumLength(Register dst, Register map) { |
3341 STATIC_ASSERT(Map::EnumLengthBits::kShift == 0); | 3341 STATIC_ASSERT(Map::EnumLengthBits::kShift == 0); |
3342 movp(dst, FieldOperand(map, Map::kBitField3Offset)); | 3342 movp(dst, FieldOperand(map, Map::kBitField3Offset)); |
3343 Move(kScratchRegister, Smi::FromInt(Map::EnumLengthBits::kMask)); | 3343 Move(kScratchRegister, Smi::FromInt(Map::EnumLengthBits::kMask)); |
3344 and_(dst, kScratchRegister); | 3344 andp(dst, kScratchRegister); |
3345 } | 3345 } |
3346 | 3346 |
3347 | 3347 |
3348 void MacroAssembler::DispatchMap(Register obj, | 3348 void MacroAssembler::DispatchMap(Register obj, |
3349 Register unused, | 3349 Register unused, |
3350 Handle<Map> map, | 3350 Handle<Map> map, |
3351 Handle<Code> success, | 3351 Handle<Code> success, |
3352 SmiCheckType smi_check_type) { | 3352 SmiCheckType smi_check_type) { |
3353 Label fail; | 3353 Label fail; |
3354 if (smi_check_type == DO_SMI_CHECK) { | 3354 if (smi_check_type == DO_SMI_CHECK) { |
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3835 } | 3835 } |
3836 } else if (arg_stack_space > 0) { | 3836 } else if (arg_stack_space > 0) { |
3837 subp(rsp, Immediate(arg_stack_space * kRegisterSize)); | 3837 subp(rsp, Immediate(arg_stack_space * kRegisterSize)); |
3838 } | 3838 } |
3839 | 3839 |
3840 // Get the required frame alignment for the OS. | 3840 // Get the required frame alignment for the OS. |
3841 const int kFrameAlignment = OS::ActivationFrameAlignment(); | 3841 const int kFrameAlignment = OS::ActivationFrameAlignment(); |
3842 if (kFrameAlignment > 0) { | 3842 if (kFrameAlignment > 0) { |
3843 ASSERT(IsPowerOf2(kFrameAlignment)); | 3843 ASSERT(IsPowerOf2(kFrameAlignment)); |
3844 ASSERT(is_int8(kFrameAlignment)); | 3844 ASSERT(is_int8(kFrameAlignment)); |
3845 and_(rsp, Immediate(-kFrameAlignment)); | 3845 andp(rsp, Immediate(-kFrameAlignment)); |
3846 } | 3846 } |
3847 | 3847 |
3848 // Patch the saved entry sp. | 3848 // Patch the saved entry sp. |
3849 movp(Operand(rbp, ExitFrameConstants::kSPOffset), rsp); | 3849 movp(Operand(rbp, ExitFrameConstants::kSPOffset), rsp); |
3850 } | 3850 } |
3851 | 3851 |
3852 | 3852 |
3853 void MacroAssembler::EnterExitFrame(int arg_stack_space, bool save_doubles) { | 3853 void MacroAssembler::EnterExitFrame(int arg_stack_space, bool save_doubles) { |
3854 EnterExitFramePrologue(true); | 3854 EnterExitFramePrologue(true); |
3855 | 3855 |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4061 decl(r1); | 4061 decl(r1); |
4062 | 4062 |
4063 // Generate an unrolled loop that performs a few probes before giving up. | 4063 // Generate an unrolled loop that performs a few probes before giving up. |
4064 for (int i = 0; i < kNumberDictionaryProbes; i++) { | 4064 for (int i = 0; i < kNumberDictionaryProbes; i++) { |
4065 // Use r2 for index calculations and keep the hash intact in r0. | 4065 // Use r2 for index calculations and keep the hash intact in r0. |
4066 movp(r2, r0); | 4066 movp(r2, r0); |
4067 // Compute the masked index: (hash + i + i * i) & mask. | 4067 // Compute the masked index: (hash + i + i * i) & mask. |
4068 if (i > 0) { | 4068 if (i > 0) { |
4069 addl(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i))); | 4069 addl(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i))); |
4070 } | 4070 } |
4071 and_(r2, r1); | 4071 andp(r2, r1); |
4072 | 4072 |
4073 // Scale the index by multiplying by the entry size. | 4073 // Scale the index by multiplying by the entry size. |
4074 ASSERT(SeededNumberDictionary::kEntrySize == 3); | 4074 ASSERT(SeededNumberDictionary::kEntrySize == 3); |
4075 leap(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 | 4075 leap(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 |
4076 | 4076 |
4077 // Check if the key matches. | 4077 // Check if the key matches. |
4078 cmpp(key, FieldOperand(elements, | 4078 cmpp(key, FieldOperand(elements, |
4079 r2, | 4079 r2, |
4080 times_pointer_size, | 4080 times_pointer_size, |
4081 SeededNumberDictionary::kElementsStartOffset)); | 4081 SeededNumberDictionary::kElementsStartOffset)); |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4286 addp(result, Immediate(kHeapObjectTag)); | 4286 addp(result, Immediate(kHeapObjectTag)); |
4287 } | 4287 } |
4288 } | 4288 } |
4289 | 4289 |
4290 | 4290 |
4291 void MacroAssembler::UndoAllocationInNewSpace(Register object) { | 4291 void MacroAssembler::UndoAllocationInNewSpace(Register object) { |
4292 ExternalReference new_space_allocation_top = | 4292 ExternalReference new_space_allocation_top = |
4293 ExternalReference::new_space_allocation_top_address(isolate()); | 4293 ExternalReference::new_space_allocation_top_address(isolate()); |
4294 | 4294 |
4295 // Make sure the object has no tag before resetting top. | 4295 // Make sure the object has no tag before resetting top. |
4296 and_(object, Immediate(~kHeapObjectTagMask)); | 4296 andp(object, Immediate(~kHeapObjectTagMask)); |
4297 Operand top_operand = ExternalOperand(new_space_allocation_top); | 4297 Operand top_operand = ExternalOperand(new_space_allocation_top); |
4298 #ifdef DEBUG | 4298 #ifdef DEBUG |
4299 cmpp(object, top_operand); | 4299 cmpp(object, top_operand); |
4300 Check(below, kUndoAllocationOfNonAllocatedMemory); | 4300 Check(below, kUndoAllocationOfNonAllocatedMemory); |
4301 #endif | 4301 #endif |
4302 movp(top_operand, object); | 4302 movp(top_operand, object); |
4303 } | 4303 } |
4304 | 4304 |
4305 | 4305 |
4306 void MacroAssembler::AllocateHeapNumber(Register result, | 4306 void MacroAssembler::AllocateHeapNumber(Register result, |
(...skipping 15 matching lines...) Expand all Loading... |
4322 Register scratch3, | 4322 Register scratch3, |
4323 Label* gc_required) { | 4323 Label* gc_required) { |
4324 // Calculate the number of bytes needed for the characters in the string while | 4324 // Calculate the number of bytes needed for the characters in the string while |
4325 // observing object alignment. | 4325 // observing object alignment. |
4326 const int kHeaderAlignment = SeqTwoByteString::kHeaderSize & | 4326 const int kHeaderAlignment = SeqTwoByteString::kHeaderSize & |
4327 kObjectAlignmentMask; | 4327 kObjectAlignmentMask; |
4328 ASSERT(kShortSize == 2); | 4328 ASSERT(kShortSize == 2); |
4329 // scratch1 = length * 2 + kObjectAlignmentMask. | 4329 // scratch1 = length * 2 + kObjectAlignmentMask. |
4330 leap(scratch1, Operand(length, length, times_1, kObjectAlignmentMask + | 4330 leap(scratch1, Operand(length, length, times_1, kObjectAlignmentMask + |
4331 kHeaderAlignment)); | 4331 kHeaderAlignment)); |
4332 and_(scratch1, Immediate(~kObjectAlignmentMask)); | 4332 andp(scratch1, Immediate(~kObjectAlignmentMask)); |
4333 if (kHeaderAlignment > 0) { | 4333 if (kHeaderAlignment > 0) { |
4334 subp(scratch1, Immediate(kHeaderAlignment)); | 4334 subp(scratch1, Immediate(kHeaderAlignment)); |
4335 } | 4335 } |
4336 | 4336 |
4337 // Allocate two byte string in new space. | 4337 // Allocate two byte string in new space. |
4338 Allocate(SeqTwoByteString::kHeaderSize, | 4338 Allocate(SeqTwoByteString::kHeaderSize, |
4339 times_1, | 4339 times_1, |
4340 scratch1, | 4340 scratch1, |
4341 result, | 4341 result, |
4342 scratch2, | 4342 scratch2, |
(...skipping 17 matching lines...) Expand all Loading... |
4360 Register scratch2, | 4360 Register scratch2, |
4361 Register scratch3, | 4361 Register scratch3, |
4362 Label* gc_required) { | 4362 Label* gc_required) { |
4363 // Calculate the number of bytes needed for the characters in the string while | 4363 // Calculate the number of bytes needed for the characters in the string while |
4364 // observing object alignment. | 4364 // observing object alignment. |
4365 const int kHeaderAlignment = SeqOneByteString::kHeaderSize & | 4365 const int kHeaderAlignment = SeqOneByteString::kHeaderSize & |
4366 kObjectAlignmentMask; | 4366 kObjectAlignmentMask; |
4367 movl(scratch1, length); | 4367 movl(scratch1, length); |
4368 ASSERT(kCharSize == 1); | 4368 ASSERT(kCharSize == 1); |
4369 addp(scratch1, Immediate(kObjectAlignmentMask + kHeaderAlignment)); | 4369 addp(scratch1, Immediate(kObjectAlignmentMask + kHeaderAlignment)); |
4370 and_(scratch1, Immediate(~kObjectAlignmentMask)); | 4370 andp(scratch1, Immediate(~kObjectAlignmentMask)); |
4371 if (kHeaderAlignment > 0) { | 4371 if (kHeaderAlignment > 0) { |
4372 subp(scratch1, Immediate(kHeaderAlignment)); | 4372 subp(scratch1, Immediate(kHeaderAlignment)); |
4373 } | 4373 } |
4374 | 4374 |
4375 // Allocate ASCII string in new space. | 4375 // Allocate ASCII string in new space. |
4376 Allocate(SeqOneByteString::kHeaderSize, | 4376 Allocate(SeqOneByteString::kHeaderSize, |
4377 times_1, | 4377 times_1, |
4378 scratch1, | 4378 scratch1, |
4379 result, | 4379 result, |
4380 scratch2, | 4380 scratch2, |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4713 int frame_alignment = OS::ActivationFrameAlignment(); | 4713 int frame_alignment = OS::ActivationFrameAlignment(); |
4714 ASSERT(frame_alignment != 0); | 4714 ASSERT(frame_alignment != 0); |
4715 ASSERT(num_arguments >= 0); | 4715 ASSERT(num_arguments >= 0); |
4716 | 4716 |
4717 // Make stack end at alignment and allocate space for arguments and old rsp. | 4717 // Make stack end at alignment and allocate space for arguments and old rsp. |
4718 movp(kScratchRegister, rsp); | 4718 movp(kScratchRegister, rsp); |
4719 ASSERT(IsPowerOf2(frame_alignment)); | 4719 ASSERT(IsPowerOf2(frame_alignment)); |
4720 int argument_slots_on_stack = | 4720 int argument_slots_on_stack = |
4721 ArgumentStackSlotsForCFunctionCall(num_arguments); | 4721 ArgumentStackSlotsForCFunctionCall(num_arguments); |
4722 subp(rsp, Immediate((argument_slots_on_stack + 1) * kRegisterSize)); | 4722 subp(rsp, Immediate((argument_slots_on_stack + 1) * kRegisterSize)); |
4723 and_(rsp, Immediate(-frame_alignment)); | 4723 andp(rsp, Immediate(-frame_alignment)); |
4724 movp(Operand(rsp, argument_slots_on_stack * kRegisterSize), kScratchRegister); | 4724 movp(Operand(rsp, argument_slots_on_stack * kRegisterSize), kScratchRegister); |
4725 } | 4725 } |
4726 | 4726 |
4727 | 4727 |
4728 void MacroAssembler::CallCFunction(ExternalReference function, | 4728 void MacroAssembler::CallCFunction(ExternalReference function, |
4729 int num_arguments) { | 4729 int num_arguments) { |
4730 LoadAddress(rax, function); | 4730 LoadAddress(rax, function); |
4731 CallCFunction(rax, num_arguments); | 4731 CallCFunction(rax, num_arguments); |
4732 } | 4732 } |
4733 | 4733 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4782 | 4782 |
4783 void MacroAssembler::CheckPageFlag( | 4783 void MacroAssembler::CheckPageFlag( |
4784 Register object, | 4784 Register object, |
4785 Register scratch, | 4785 Register scratch, |
4786 int mask, | 4786 int mask, |
4787 Condition cc, | 4787 Condition cc, |
4788 Label* condition_met, | 4788 Label* condition_met, |
4789 Label::Distance condition_met_distance) { | 4789 Label::Distance condition_met_distance) { |
4790 ASSERT(cc == zero || cc == not_zero); | 4790 ASSERT(cc == zero || cc == not_zero); |
4791 if (scratch.is(object)) { | 4791 if (scratch.is(object)) { |
4792 and_(scratch, Immediate(~Page::kPageAlignmentMask)); | 4792 andp(scratch, Immediate(~Page::kPageAlignmentMask)); |
4793 } else { | 4793 } else { |
4794 movp(scratch, Immediate(~Page::kPageAlignmentMask)); | 4794 movp(scratch, Immediate(~Page::kPageAlignmentMask)); |
4795 and_(scratch, object); | 4795 andp(scratch, object); |
4796 } | 4796 } |
4797 if (mask < (1 << kBitsPerByte)) { | 4797 if (mask < (1 << kBitsPerByte)) { |
4798 testb(Operand(scratch, MemoryChunk::kFlagsOffset), | 4798 testb(Operand(scratch, MemoryChunk::kFlagsOffset), |
4799 Immediate(static_cast<uint8_t>(mask))); | 4799 Immediate(static_cast<uint8_t>(mask))); |
4800 } else { | 4800 } else { |
4801 testl(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask)); | 4801 testl(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask)); |
4802 } | 4802 } |
4803 j(cc, condition_met, condition_met_distance); | 4803 j(cc, condition_met, condition_met_distance); |
4804 } | 4804 } |
4805 | 4805 |
4806 | 4806 |
4807 void MacroAssembler::CheckMapDeprecated(Handle<Map> map, | 4807 void MacroAssembler::CheckMapDeprecated(Handle<Map> map, |
4808 Register scratch, | 4808 Register scratch, |
4809 Label* if_deprecated) { | 4809 Label* if_deprecated) { |
4810 if (map->CanBeDeprecated()) { | 4810 if (map->CanBeDeprecated()) { |
4811 Move(scratch, map); | 4811 Move(scratch, map); |
4812 movp(scratch, FieldOperand(scratch, Map::kBitField3Offset)); | 4812 movp(scratch, FieldOperand(scratch, Map::kBitField3Offset)); |
4813 SmiToInteger32(scratch, scratch); | 4813 SmiToInteger32(scratch, scratch); |
4814 and_(scratch, Immediate(Map::Deprecated::kMask)); | 4814 andp(scratch, Immediate(Map::Deprecated::kMask)); |
4815 j(not_zero, if_deprecated); | 4815 j(not_zero, if_deprecated); |
4816 } | 4816 } |
4817 } | 4817 } |
4818 | 4818 |
4819 | 4819 |
4820 void MacroAssembler::JumpIfBlack(Register object, | 4820 void MacroAssembler::JumpIfBlack(Register object, |
4821 Register bitmap_scratch, | 4821 Register bitmap_scratch, |
4822 Register mask_scratch, | 4822 Register mask_scratch, |
4823 Label* on_black, | 4823 Label* on_black, |
4824 Label::Distance on_black_distance) { | 4824 Label::Distance on_black_distance) { |
4825 ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, rcx)); | 4825 ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, rcx)); |
4826 GetMarkBits(object, bitmap_scratch, mask_scratch); | 4826 GetMarkBits(object, bitmap_scratch, mask_scratch); |
4827 | 4827 |
4828 ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); | 4828 ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); |
4829 // The mask_scratch register contains a 1 at the position of the first bit | 4829 // The mask_scratch register contains a 1 at the position of the first bit |
4830 // and a 0 at all other positions, including the position of the second bit. | 4830 // and a 0 at all other positions, including the position of the second bit. |
4831 movp(rcx, mask_scratch); | 4831 movp(rcx, mask_scratch); |
4832 // Make rcx into a mask that covers both marking bits using the operation | 4832 // Make rcx into a mask that covers both marking bits using the operation |
4833 // rcx = mask | (mask << 1). | 4833 // rcx = mask | (mask << 1). |
4834 leap(rcx, Operand(mask_scratch, mask_scratch, times_2, 0)); | 4834 leap(rcx, Operand(mask_scratch, mask_scratch, times_2, 0)); |
4835 // Note that we are using a 4-byte aligned 8-byte load. | 4835 // Note that we are using a 4-byte aligned 8-byte load. |
4836 and_(rcx, Operand(bitmap_scratch, MemoryChunk::kHeaderSize)); | 4836 andp(rcx, Operand(bitmap_scratch, MemoryChunk::kHeaderSize)); |
4837 cmpp(mask_scratch, rcx); | 4837 cmpp(mask_scratch, rcx); |
4838 j(equal, on_black, on_black_distance); | 4838 j(equal, on_black, on_black_distance); |
4839 } | 4839 } |
4840 | 4840 |
4841 | 4841 |
4842 // Detect some, but not all, common pointer-free objects. This is used by the | 4842 // Detect some, but not all, common pointer-free objects. This is used by the |
4843 // incremental write barrier which doesn't care about oddballs (they are always | 4843 // incremental write barrier which doesn't care about oddballs (they are always |
4844 // marked black immediately so this code is not hit). | 4844 // marked black immediately so this code is not hit). |
4845 void MacroAssembler::JumpIfDataObject( | 4845 void MacroAssembler::JumpIfDataObject( |
4846 Register value, | 4846 Register value, |
(...skipping 14 matching lines...) Expand all Loading... |
4861 bind(&is_data_object); | 4861 bind(&is_data_object); |
4862 } | 4862 } |
4863 | 4863 |
4864 | 4864 |
4865 void MacroAssembler::GetMarkBits(Register addr_reg, | 4865 void MacroAssembler::GetMarkBits(Register addr_reg, |
4866 Register bitmap_reg, | 4866 Register bitmap_reg, |
4867 Register mask_reg) { | 4867 Register mask_reg) { |
4868 ASSERT(!AreAliased(addr_reg, bitmap_reg, mask_reg, rcx)); | 4868 ASSERT(!AreAliased(addr_reg, bitmap_reg, mask_reg, rcx)); |
4869 movp(bitmap_reg, addr_reg); | 4869 movp(bitmap_reg, addr_reg); |
4870 // Sign extended 32 bit immediate. | 4870 // Sign extended 32 bit immediate. |
4871 and_(bitmap_reg, Immediate(~Page::kPageAlignmentMask)); | 4871 andp(bitmap_reg, Immediate(~Page::kPageAlignmentMask)); |
4872 movp(rcx, addr_reg); | 4872 movp(rcx, addr_reg); |
4873 int shift = | 4873 int shift = |
4874 Bitmap::kBitsPerCellLog2 + kPointerSizeLog2 - Bitmap::kBytesPerCellLog2; | 4874 Bitmap::kBitsPerCellLog2 + kPointerSizeLog2 - Bitmap::kBytesPerCellLog2; |
4875 shrl(rcx, Immediate(shift)); | 4875 shrl(rcx, Immediate(shift)); |
4876 and_(rcx, | 4876 andp(rcx, |
4877 Immediate((Page::kPageAlignmentMask >> shift) & | 4877 Immediate((Page::kPageAlignmentMask >> shift) & |
4878 ~(Bitmap::kBytesPerCell - 1))); | 4878 ~(Bitmap::kBytesPerCell - 1))); |
4879 | 4879 |
4880 addp(bitmap_reg, rcx); | 4880 addp(bitmap_reg, rcx); |
4881 movp(rcx, addr_reg); | 4881 movp(rcx, addr_reg); |
4882 shrl(rcx, Immediate(kPointerSizeLog2)); | 4882 shrl(rcx, Immediate(kPointerSizeLog2)); |
4883 and_(rcx, Immediate((1 << Bitmap::kBitsPerCellLog2) - 1)); | 4883 andp(rcx, Immediate((1 << Bitmap::kBitsPerCellLog2) - 1)); |
4884 movl(mask_reg, Immediate(1)); | 4884 movl(mask_reg, Immediate(1)); |
4885 shl_cl(mask_reg); | 4885 shl_cl(mask_reg); |
4886 } | 4886 } |
4887 | 4887 |
4888 | 4888 |
4889 void MacroAssembler::EnsureNotWhite( | 4889 void MacroAssembler::EnsureNotWhite( |
4890 Register value, | 4890 Register value, |
4891 Register bitmap_scratch, | 4891 Register bitmap_scratch, |
4892 Register mask_scratch, | 4892 Register mask_scratch, |
4893 Label* value_is_white_and_not_data, | 4893 Label* value_is_white_and_not_data, |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4954 ASSERT_EQ(0, kSeqStringTag & kExternalStringTag); | 4954 ASSERT_EQ(0, kSeqStringTag & kExternalStringTag); |
4955 ASSERT_EQ(0, kConsStringTag & kExternalStringTag); | 4955 ASSERT_EQ(0, kConsStringTag & kExternalStringTag); |
4956 testb(instance_type, Immediate(kExternalStringTag)); | 4956 testb(instance_type, Immediate(kExternalStringTag)); |
4957 j(zero, ¬_external, Label::kNear); | 4957 j(zero, ¬_external, Label::kNear); |
4958 movp(length, Immediate(ExternalString::kSize)); | 4958 movp(length, Immediate(ExternalString::kSize)); |
4959 jmp(&is_data_object, Label::kNear); | 4959 jmp(&is_data_object, Label::kNear); |
4960 | 4960 |
4961 bind(¬_external); | 4961 bind(¬_external); |
4962 // Sequential string, either ASCII or UC16. | 4962 // Sequential string, either ASCII or UC16. |
4963 ASSERT(kOneByteStringTag == 0x04); | 4963 ASSERT(kOneByteStringTag == 0x04); |
4964 and_(length, Immediate(kStringEncodingMask)); | 4964 andp(length, Immediate(kStringEncodingMask)); |
4965 xor_(length, Immediate(kStringEncodingMask)); | 4965 xorp(length, Immediate(kStringEncodingMask)); |
4966 addp(length, Immediate(0x04)); | 4966 addp(length, Immediate(0x04)); |
4967 // Value now either 4 (if ASCII) or 8 (if UC16), i.e. char-size shifted by 2. | 4967 // Value now either 4 (if ASCII) or 8 (if UC16), i.e. char-size shifted by 2. |
4968 imulp(length, FieldOperand(value, String::kLengthOffset)); | 4968 imulp(length, FieldOperand(value, String::kLengthOffset)); |
4969 shr(length, Immediate(2 + kSmiTagSize + kSmiShiftSize)); | 4969 shr(length, Immediate(2 + kSmiTagSize + kSmiShiftSize)); |
4970 addp(length, Immediate(SeqString::kHeaderSize + kObjectAlignmentMask)); | 4970 addp(length, Immediate(SeqString::kHeaderSize + kObjectAlignmentMask)); |
4971 and_(length, Immediate(~kObjectAlignmentMask)); | 4971 andp(length, Immediate(~kObjectAlignmentMask)); |
4972 | 4972 |
4973 bind(&is_data_object); | 4973 bind(&is_data_object); |
4974 // Value is a data object, and it is white. Mark it black. Since we know | 4974 // Value is a data object, and it is white. Mark it black. Since we know |
4975 // that the object is white we can make it black by flipping one bit. | 4975 // that the object is white we can make it black by flipping one bit. |
4976 or_(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch); | 4976 orp(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch); |
4977 | 4977 |
4978 and_(bitmap_scratch, Immediate(~Page::kPageAlignmentMask)); | 4978 andp(bitmap_scratch, Immediate(~Page::kPageAlignmentMask)); |
4979 addl(Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset), length); | 4979 addl(Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset), length); |
4980 | 4980 |
4981 bind(&done); | 4981 bind(&done); |
4982 } | 4982 } |
4983 | 4983 |
4984 | 4984 |
4985 void MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) { | 4985 void MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) { |
4986 Label next, start; | 4986 Label next, start; |
4987 Register empty_fixed_array_value = r8; | 4987 Register empty_fixed_array_value = r8; |
4988 LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex); | 4988 LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5057 ASSERT(!scratch1.is(scratch0)); | 5057 ASSERT(!scratch1.is(scratch0)); |
5058 Register current = scratch0; | 5058 Register current = scratch0; |
5059 Label loop_again; | 5059 Label loop_again; |
5060 | 5060 |
5061 movp(current, object); | 5061 movp(current, object); |
5062 | 5062 |
5063 // Loop based on the map going up the prototype chain. | 5063 // Loop based on the map going up the prototype chain. |
5064 bind(&loop_again); | 5064 bind(&loop_again); |
5065 movp(current, FieldOperand(current, HeapObject::kMapOffset)); | 5065 movp(current, FieldOperand(current, HeapObject::kMapOffset)); |
5066 movp(scratch1, FieldOperand(current, Map::kBitField2Offset)); | 5066 movp(scratch1, FieldOperand(current, Map::kBitField2Offset)); |
5067 and_(scratch1, Immediate(Map::kElementsKindMask)); | 5067 andp(scratch1, Immediate(Map::kElementsKindMask)); |
5068 shr(scratch1, Immediate(Map::kElementsKindShift)); | 5068 shr(scratch1, Immediate(Map::kElementsKindShift)); |
5069 cmpp(scratch1, Immediate(DICTIONARY_ELEMENTS)); | 5069 cmpp(scratch1, Immediate(DICTIONARY_ELEMENTS)); |
5070 j(equal, found); | 5070 j(equal, found); |
5071 movp(current, FieldOperand(current, Map::kPrototypeOffset)); | 5071 movp(current, FieldOperand(current, Map::kPrototypeOffset)); |
5072 CompareRoot(current, Heap::kNullValueRootIndex); | 5072 CompareRoot(current, Heap::kNullValueRootIndex); |
5073 j(not_equal, &loop_again); | 5073 j(not_equal, &loop_again); |
5074 } | 5074 } |
5075 | 5075 |
5076 | 5076 |
5077 void MacroAssembler::TruncatingDiv(Register dividend, int32_t divisor) { | 5077 void MacroAssembler::TruncatingDiv(Register dividend, int32_t divisor) { |
5078 ASSERT(!dividend.is(rax)); | 5078 ASSERT(!dividend.is(rax)); |
5079 ASSERT(!dividend.is(rdx)); | 5079 ASSERT(!dividend.is(rdx)); |
5080 MultiplierAndShift ms(divisor); | 5080 MultiplierAndShift ms(divisor); |
5081 movl(rax, Immediate(ms.multiplier())); | 5081 movl(rax, Immediate(ms.multiplier())); |
5082 imull(dividend); | 5082 imull(dividend); |
5083 if (divisor > 0 && ms.multiplier() < 0) addl(rdx, dividend); | 5083 if (divisor > 0 && ms.multiplier() < 0) addl(rdx, dividend); |
5084 if (divisor < 0 && ms.multiplier() > 0) subl(rdx, dividend); | 5084 if (divisor < 0 && ms.multiplier() > 0) subl(rdx, dividend); |
5085 if (ms.shift() > 0) sarl(rdx, Immediate(ms.shift())); | 5085 if (ms.shift() > 0) sarl(rdx, Immediate(ms.shift())); |
5086 movl(rax, dividend); | 5086 movl(rax, dividend); |
5087 shrl(rax, Immediate(31)); | 5087 shrl(rax, Immediate(31)); |
5088 addl(rdx, rax); | 5088 addl(rdx, rax); |
5089 } | 5089 } |
5090 | 5090 |
5091 | 5091 |
5092 } } // namespace v8::internal | 5092 } } // namespace v8::internal |
5093 | 5093 |
5094 #endif // V8_TARGET_ARCH_X64 | 5094 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |