| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 Heap::RootListIndex index) { | 85 Heap::RootListIndex index) { |
| 86 ASSERT(!with.AddressUsesRegister(kScratchRegister)); | 86 ASSERT(!with.AddressUsesRegister(kScratchRegister)); |
| 87 LoadRoot(kScratchRegister, index); | 87 LoadRoot(kScratchRegister, index); |
| 88 cmpq(with, kScratchRegister); | 88 cmpq(with, kScratchRegister); |
| 89 } | 89 } |
| 90 | 90 |
| 91 | 91 |
| 92 void MacroAssembler::RecordWriteHelper(Register object, | 92 void MacroAssembler::RecordWriteHelper(Register object, |
| 93 Register addr, | 93 Register addr, |
| 94 Register scratch) { | 94 Register scratch) { |
| 95 if (FLAG_debug_code) { | 95 if (emit_debug_code()) { |
| 96 // Check that the object is not in new space. | 96 // Check that the object is not in new space. |
| 97 NearLabel not_in_new_space; | 97 NearLabel not_in_new_space; |
| 98 InNewSpace(object, scratch, not_equal, ¬_in_new_space); | 98 InNewSpace(object, scratch, not_equal, ¬_in_new_space); |
| 99 Abort("new-space object passed to RecordWriteHelper"); | 99 Abort("new-space object passed to RecordWriteHelper"); |
| 100 bind(¬_in_new_space); | 100 bind(¬_in_new_space); |
| 101 } | 101 } |
| 102 | 102 |
| 103 // Compute the page start address from the heap object pointer, and reuse | 103 // Compute the page start address from the heap object pointer, and reuse |
| 104 // the 'object' register for it. | 104 // the 'object' register for it. |
| 105 and_(object, Immediate(~Page::kPageAlignmentMask)); | 105 and_(object, Immediate(~Page::kPageAlignmentMask)); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 117 void MacroAssembler::RecordWrite(Register object, | 117 void MacroAssembler::RecordWrite(Register object, |
| 118 int offset, | 118 int offset, |
| 119 Register value, | 119 Register value, |
| 120 Register index) { | 120 Register index) { |
| 121 // The compiled code assumes that record write doesn't change the | 121 // The compiled code assumes that record write doesn't change the |
| 122 // context register, so we check that none of the clobbered | 122 // context register, so we check that none of the clobbered |
| 123 // registers are rsi. | 123 // registers are rsi. |
| 124 ASSERT(!object.is(rsi) && !value.is(rsi) && !index.is(rsi)); | 124 ASSERT(!object.is(rsi) && !value.is(rsi) && !index.is(rsi)); |
| 125 | 125 |
| 126 // First, check if a write barrier is even needed. The tests below | 126 // First, check if a write barrier is even needed. The tests below |
| 127 // catch stores of Smis and stores into young gen. | 127 // catch stores of smis and stores into the young generation. |
| 128 Label done; | 128 Label done; |
| 129 JumpIfSmi(value, &done); | 129 JumpIfSmi(value, &done); |
| 130 | 130 |
| 131 RecordWriteNonSmi(object, offset, value, index); | 131 RecordWriteNonSmi(object, offset, value, index); |
| 132 bind(&done); | 132 bind(&done); |
| 133 | 133 |
| 134 // Clobber all input registers when running with the debug-code flag | 134 // Clobber all input registers when running with the debug-code flag |
| 135 // turned on to provoke errors. This clobbering repeats the | 135 // turned on to provoke errors. This clobbering repeats the |
| 136 // clobbering done inside RecordWriteNonSmi but it's necessary to | 136 // clobbering done inside RecordWriteNonSmi but it's necessary to |
| 137 // avoid having the fast case for smis leave the registers | 137 // avoid having the fast case for smis leave the registers |
| 138 // unchanged. | 138 // unchanged. |
| 139 if (FLAG_debug_code) { | 139 if (emit_debug_code()) { |
| 140 movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 140 movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 141 movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 141 movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 142 movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 142 movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 143 } | 143 } |
| 144 } | 144 } |
| 145 | 145 |
| 146 | 146 |
| 147 void MacroAssembler::RecordWrite(Register object, | 147 void MacroAssembler::RecordWrite(Register object, |
| 148 Register address, | 148 Register address, |
| 149 Register value) { | 149 Register value) { |
| 150 // The compiled code assumes that record write doesn't change the | 150 // The compiled code assumes that record write doesn't change the |
| 151 // context register, so we check that none of the clobbered | 151 // context register, so we check that none of the clobbered |
| 152 // registers are rsi. | 152 // registers are rsi. |
| 153 ASSERT(!object.is(rsi) && !value.is(rsi) && !address.is(rsi)); | 153 ASSERT(!object.is(rsi) && !value.is(rsi) && !address.is(rsi)); |
| 154 | 154 |
| 155 // First, check if a write barrier is even needed. The tests below | 155 // First, check if a write barrier is even needed. The tests below |
| 156 // catch stores of Smis and stores into young gen. | 156 // catch stores of smis and stores into the young generation. |
| 157 Label done; | 157 Label done; |
| 158 JumpIfSmi(value, &done); | 158 JumpIfSmi(value, &done); |
| 159 | 159 |
| 160 InNewSpace(object, value, equal, &done); | 160 InNewSpace(object, value, equal, &done); |
| 161 | 161 |
| 162 RecordWriteHelper(object, address, value); | 162 RecordWriteHelper(object, address, value); |
| 163 | 163 |
| 164 bind(&done); | 164 bind(&done); |
| 165 | 165 |
| 166 // Clobber all input registers when running with the debug-code flag | 166 // Clobber all input registers when running with the debug-code flag |
| 167 // turned on to provoke errors. | 167 // turned on to provoke errors. |
| 168 if (FLAG_debug_code) { | 168 if (emit_debug_code()) { |
| 169 movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 169 movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 170 movq(address, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 170 movq(address, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 171 movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 171 movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 172 } | 172 } |
| 173 } | 173 } |
| 174 | 174 |
| 175 | 175 |
| 176 void MacroAssembler::RecordWriteNonSmi(Register object, | 176 void MacroAssembler::RecordWriteNonSmi(Register object, |
| 177 int offset, | 177 int offset, |
| 178 Register scratch, | 178 Register scratch, |
| 179 Register index) { | 179 Register index) { |
| 180 Label done; | 180 Label done; |
| 181 | 181 |
| 182 if (FLAG_debug_code) { | 182 if (emit_debug_code()) { |
| 183 NearLabel okay; | 183 NearLabel okay; |
| 184 JumpIfNotSmi(object, &okay); | 184 JumpIfNotSmi(object, &okay); |
| 185 Abort("MacroAssembler::RecordWriteNonSmi cannot deal with smis"); | 185 Abort("MacroAssembler::RecordWriteNonSmi cannot deal with smis"); |
| 186 bind(&okay); | 186 bind(&okay); |
| 187 | 187 |
| 188 if (offset == 0) { | 188 if (offset == 0) { |
| 189 // index must be int32. | 189 // index must be int32. |
| 190 Register tmp = index.is(rax) ? rbx : rax; | 190 Register tmp = index.is(rax) ? rbx : rax; |
| 191 push(tmp); | 191 push(tmp); |
| 192 movl(tmp, index); | 192 movl(tmp, index); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 216 index, | 216 index, |
| 217 times_pointer_size, | 217 times_pointer_size, |
| 218 FixedArray::kHeaderSize)); | 218 FixedArray::kHeaderSize)); |
| 219 } | 219 } |
| 220 RecordWriteHelper(object, dst, scratch); | 220 RecordWriteHelper(object, dst, scratch); |
| 221 | 221 |
| 222 bind(&done); | 222 bind(&done); |
| 223 | 223 |
| 224 // Clobber all input registers when running with the debug-code flag | 224 // Clobber all input registers when running with the debug-code flag |
| 225 // turned on to provoke errors. | 225 // turned on to provoke errors. |
| 226 if (FLAG_debug_code) { | 226 if (emit_debug_code()) { |
| 227 movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 227 movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 228 movq(scratch, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 228 movq(scratch, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 229 movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 229 movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 230 } | 230 } |
| 231 } | 231 } |
| 232 | 232 |
| 233 void MacroAssembler::Assert(Condition cc, const char* msg) { | 233 void MacroAssembler::Assert(Condition cc, const char* msg) { |
| 234 if (FLAG_debug_code) Check(cc, msg); | 234 if (emit_debug_code()) Check(cc, msg); |
| 235 } | 235 } |
| 236 | 236 |
| 237 | 237 |
| 238 void MacroAssembler::AssertFastElements(Register elements) { | 238 void MacroAssembler::AssertFastElements(Register elements) { |
| 239 if (FLAG_debug_code) { | 239 if (emit_debug_code()) { |
| 240 NearLabel ok; | 240 NearLabel ok; |
| 241 CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), | 241 CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), |
| 242 Heap::kFixedArrayMapRootIndex); | 242 Heap::kFixedArrayMapRootIndex); |
| 243 j(equal, &ok); | 243 j(equal, &ok); |
| 244 CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), | 244 CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), |
| 245 Heap::kFixedCOWArrayMapRootIndex); | 245 Heap::kFixedCOWArrayMapRootIndex); |
| 246 j(equal, &ok); | 246 j(equal, &ok); |
| 247 Abort("JSObject with fast elements map has slow elements"); | 247 Abort("JSObject with fast elements map has slow elements"); |
| 248 bind(&ok); | 248 bind(&ok); |
| 249 } | 249 } |
| (...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 706 return kScratchRegister; | 706 return kScratchRegister; |
| 707 } | 707 } |
| 708 if (value == 1) { | 708 if (value == 1) { |
| 709 return kSmiConstantRegister; | 709 return kSmiConstantRegister; |
| 710 } | 710 } |
| 711 LoadSmiConstant(kScratchRegister, source); | 711 LoadSmiConstant(kScratchRegister, source); |
| 712 return kScratchRegister; | 712 return kScratchRegister; |
| 713 } | 713 } |
| 714 | 714 |
| 715 void MacroAssembler::LoadSmiConstant(Register dst, Smi* source) { | 715 void MacroAssembler::LoadSmiConstant(Register dst, Smi* source) { |
| 716 if (FLAG_debug_code) { | 716 if (emit_debug_code()) { |
| 717 movq(dst, | 717 movq(dst, |
| 718 reinterpret_cast<uint64_t>(Smi::FromInt(kSmiConstantRegisterValue)), | 718 reinterpret_cast<uint64_t>(Smi::FromInt(kSmiConstantRegisterValue)), |
| 719 RelocInfo::NONE); | 719 RelocInfo::NONE); |
| 720 cmpq(dst, kSmiConstantRegister); | 720 cmpq(dst, kSmiConstantRegister); |
| 721 if (allow_stub_calls()) { | 721 if (allow_stub_calls()) { |
| 722 Assert(equal, "Uninitialized kSmiConstantRegister"); | 722 Assert(equal, "Uninitialized kSmiConstantRegister"); |
| 723 } else { | 723 } else { |
| 724 NearLabel ok; | 724 NearLabel ok; |
| 725 j(equal, &ok); | 725 j(equal, &ok); |
| 726 int3(); | 726 int3(); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 775 void MacroAssembler::Integer32ToSmi(Register dst, Register src) { | 775 void MacroAssembler::Integer32ToSmi(Register dst, Register src) { |
| 776 ASSERT_EQ(0, kSmiTag); | 776 ASSERT_EQ(0, kSmiTag); |
| 777 if (!dst.is(src)) { | 777 if (!dst.is(src)) { |
| 778 movl(dst, src); | 778 movl(dst, src); |
| 779 } | 779 } |
| 780 shl(dst, Immediate(kSmiShift)); | 780 shl(dst, Immediate(kSmiShift)); |
| 781 } | 781 } |
| 782 | 782 |
| 783 | 783 |
| 784 void MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) { | 784 void MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) { |
| 785 if (FLAG_debug_code) { | 785 if (emit_debug_code()) { |
| 786 testb(dst, Immediate(0x01)); | 786 testb(dst, Immediate(0x01)); |
| 787 NearLabel ok; | 787 NearLabel ok; |
| 788 j(zero, &ok); | 788 j(zero, &ok); |
| 789 if (allow_stub_calls()) { | 789 if (allow_stub_calls()) { |
| 790 Abort("Integer32ToSmiField writing to non-smi location"); | 790 Abort("Integer32ToSmiField writing to non-smi location"); |
| 791 } else { | 791 } else { |
| 792 int3(); | 792 int3(); |
| 793 } | 793 } |
| 794 bind(&ok); | 794 bind(&ok); |
| 795 } | 795 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 836 void MacroAssembler::SmiToInteger64(Register dst, const Operand& src) { | 836 void MacroAssembler::SmiToInteger64(Register dst, const Operand& src) { |
| 837 movsxlq(dst, Operand(src, kSmiShift / kBitsPerByte)); | 837 movsxlq(dst, Operand(src, kSmiShift / kBitsPerByte)); |
| 838 } | 838 } |
| 839 | 839 |
| 840 | 840 |
| 841 void MacroAssembler::SmiTest(Register src) { | 841 void MacroAssembler::SmiTest(Register src) { |
| 842 testq(src, src); | 842 testq(src, src); |
| 843 } | 843 } |
| 844 | 844 |
| 845 | 845 |
| 846 void MacroAssembler::SmiCompare(Register dst, Register src) { | 846 void MacroAssembler::SmiCompare(Register smi1, Register smi2) { |
| 847 cmpq(dst, src); | 847 if (emit_debug_code()) { |
| 848 AbortIfNotSmi(smi1); |
| 849 AbortIfNotSmi(smi2); |
| 850 } |
| 851 cmpq(smi1, smi2); |
| 848 } | 852 } |
| 849 | 853 |
| 850 | 854 |
| 851 void MacroAssembler::SmiCompare(Register dst, Smi* src) { | 855 void MacroAssembler::SmiCompare(Register dst, Smi* src) { |
| 856 if (emit_debug_code()) { |
| 857 AbortIfNotSmi(dst); |
| 858 } |
| 859 Cmp(dst, src); |
| 860 } |
| 861 |
| 862 |
| 863 void MacroAssembler::Cmp(Register dst, Smi* src) { |
| 852 ASSERT(!dst.is(kScratchRegister)); | 864 ASSERT(!dst.is(kScratchRegister)); |
| 853 if (src->value() == 0) { | 865 if (src->value() == 0) { |
| 854 testq(dst, dst); | 866 testq(dst, dst); |
| 855 } else { | 867 } else { |
| 856 Register constant_reg = GetSmiConstant(src); | 868 Register constant_reg = GetSmiConstant(src); |
| 857 cmpq(dst, constant_reg); | 869 cmpq(dst, constant_reg); |
| 858 } | 870 } |
| 859 } | 871 } |
| 860 | 872 |
| 861 | 873 |
| 862 void MacroAssembler::SmiCompare(Register dst, const Operand& src) { | 874 void MacroAssembler::SmiCompare(Register dst, const Operand& src) { |
| 875 if (emit_debug_code()) { |
| 876 AbortIfNotSmi(dst); |
| 877 AbortIfNotSmi(src); |
| 878 } |
| 863 cmpq(dst, src); | 879 cmpq(dst, src); |
| 864 } | 880 } |
| 865 | 881 |
| 866 | 882 |
| 867 void MacroAssembler::SmiCompare(const Operand& dst, Register src) { | 883 void MacroAssembler::SmiCompare(const Operand& dst, Register src) { |
| 884 if (emit_debug_code()) { |
| 885 AbortIfNotSmi(dst); |
| 886 AbortIfNotSmi(src); |
| 887 } |
| 868 cmpq(dst, src); | 888 cmpq(dst, src); |
| 869 } | 889 } |
| 870 | 890 |
| 871 | 891 |
| 872 void MacroAssembler::SmiCompare(const Operand& dst, Smi* src) { | 892 void MacroAssembler::SmiCompare(const Operand& dst, Smi* src) { |
| 893 if (emit_debug_code()) { |
| 894 AbortIfNotSmi(dst); |
| 895 } |
| 873 cmpl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(src->value())); | 896 cmpl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(src->value())); |
| 874 } | 897 } |
| 875 | 898 |
| 876 | 899 |
| 900 void MacroAssembler::Cmp(const Operand& dst, Smi* src) { |
| 901 // The Operand cannot use the smi register. |
| 902 Register smi_reg = GetSmiConstant(src); |
| 903 ASSERT(!dst.AddressUsesRegister(smi_reg)); |
| 904 cmpq(dst, smi_reg); |
| 905 } |
| 906 |
| 907 |
| 877 void MacroAssembler::SmiCompareInteger32(const Operand& dst, Register src) { | 908 void MacroAssembler::SmiCompareInteger32(const Operand& dst, Register src) { |
| 878 cmpl(Operand(dst, kSmiShift / kBitsPerByte), src); | 909 cmpl(Operand(dst, kSmiShift / kBitsPerByte), src); |
| 879 } | 910 } |
| 880 | 911 |
| 881 | 912 |
| 882 void MacroAssembler::PositiveSmiTimesPowerOfTwoToInteger64(Register dst, | 913 void MacroAssembler::PositiveSmiTimesPowerOfTwoToInteger64(Register dst, |
| 883 Register src, | 914 Register src, |
| 884 int power) { | 915 int power) { |
| 885 ASSERT(power >= 0); | 916 ASSERT(power >= 0); |
| 886 ASSERT(power < 64); | 917 ASSERT(power < 64); |
| (...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1351 Move(dst, Smi::cast(*source)); | 1382 Move(dst, Smi::cast(*source)); |
| 1352 } else { | 1383 } else { |
| 1353 movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT); | 1384 movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT); |
| 1354 movq(dst, kScratchRegister); | 1385 movq(dst, kScratchRegister); |
| 1355 } | 1386 } |
| 1356 } | 1387 } |
| 1357 | 1388 |
| 1358 | 1389 |
| 1359 void MacroAssembler::Cmp(Register dst, Handle<Object> source) { | 1390 void MacroAssembler::Cmp(Register dst, Handle<Object> source) { |
| 1360 if (source->IsSmi()) { | 1391 if (source->IsSmi()) { |
| 1361 SmiCompare(dst, Smi::cast(*source)); | 1392 Cmp(dst, Smi::cast(*source)); |
| 1362 } else { | 1393 } else { |
| 1363 Move(kScratchRegister, source); | 1394 Move(kScratchRegister, source); |
| 1364 cmpq(dst, kScratchRegister); | 1395 cmpq(dst, kScratchRegister); |
| 1365 } | 1396 } |
| 1366 } | 1397 } |
| 1367 | 1398 |
| 1368 | 1399 |
| 1369 void MacroAssembler::Cmp(const Operand& dst, Handle<Object> source) { | 1400 void MacroAssembler::Cmp(const Operand& dst, Handle<Object> source) { |
| 1370 if (source->IsSmi()) { | 1401 if (source->IsSmi()) { |
| 1371 SmiCompare(dst, Smi::cast(*source)); | 1402 Cmp(dst, Smi::cast(*source)); |
| 1372 } else { | 1403 } else { |
| 1373 ASSERT(source->IsHeapObject()); | 1404 ASSERT(source->IsHeapObject()); |
| 1374 movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT); | 1405 movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT); |
| 1375 cmpq(dst, kScratchRegister); | 1406 cmpq(dst, kScratchRegister); |
| 1376 } | 1407 } |
| 1377 } | 1408 } |
| 1378 | 1409 |
| 1379 | 1410 |
| 1380 void MacroAssembler::Push(Handle<Object> source) { | 1411 void MacroAssembler::Push(Handle<Object> source) { |
| 1381 if (source->IsSmi()) { | 1412 if (source->IsSmi()) { |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1753 | 1784 |
| 1754 | 1785 |
| 1755 void MacroAssembler::AbortIfSmi(Register object) { | 1786 void MacroAssembler::AbortIfSmi(Register object) { |
| 1756 NearLabel ok; | 1787 NearLabel ok; |
| 1757 Condition is_smi = CheckSmi(object); | 1788 Condition is_smi = CheckSmi(object); |
| 1758 Assert(NegateCondition(is_smi), "Operand is a smi"); | 1789 Assert(NegateCondition(is_smi), "Operand is a smi"); |
| 1759 } | 1790 } |
| 1760 | 1791 |
| 1761 | 1792 |
| 1762 void MacroAssembler::AbortIfNotSmi(Register object) { | 1793 void MacroAssembler::AbortIfNotSmi(Register object) { |
| 1763 NearLabel ok; | |
| 1764 Condition is_smi = CheckSmi(object); | 1794 Condition is_smi = CheckSmi(object); |
| 1765 Assert(is_smi, "Operand is not a smi"); | 1795 Assert(is_smi, "Operand is not a smi"); |
| 1766 } | 1796 } |
| 1797 |
| 1798 |
| 1799 void MacroAssembler::AbortIfNotSmi(const Operand& object) { |
| 1800 Condition is_smi = CheckSmi(object); |
| 1801 Assert(is_smi, "Operand is not a smi"); |
| 1802 } |
| 1767 | 1803 |
| 1768 | 1804 |
| 1769 void MacroAssembler::AbortIfNotString(Register object) { | 1805 void MacroAssembler::AbortIfNotString(Register object) { |
| 1770 testb(object, Immediate(kSmiTagMask)); | 1806 testb(object, Immediate(kSmiTagMask)); |
| 1771 Assert(not_equal, "Operand is not a string"); | 1807 Assert(not_equal, "Operand is not a string"); |
| 1772 push(object); | 1808 push(object); |
| 1773 movq(object, FieldOperand(object, HeapObject::kMapOffset)); | 1809 movq(object, FieldOperand(object, HeapObject::kMapOffset)); |
| 1774 CmpInstanceType(object, FIRST_NONSTRING_TYPE); | 1810 CmpInstanceType(object, FIRST_NONSTRING_TYPE); |
| 1775 pop(object); | 1811 pop(object); |
| 1776 Assert(below, "Operand is not a string"); | 1812 Assert(below, "Operand is not a string"); |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1991 } | 2027 } |
| 1992 | 2028 |
| 1993 | 2029 |
| 1994 void MacroAssembler::EnterFrame(StackFrame::Type type) { | 2030 void MacroAssembler::EnterFrame(StackFrame::Type type) { |
| 1995 push(rbp); | 2031 push(rbp); |
| 1996 movq(rbp, rsp); | 2032 movq(rbp, rsp); |
| 1997 push(rsi); // Context. | 2033 push(rsi); // Context. |
| 1998 Push(Smi::FromInt(type)); | 2034 Push(Smi::FromInt(type)); |
| 1999 movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); | 2035 movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); |
| 2000 push(kScratchRegister); | 2036 push(kScratchRegister); |
| 2001 if (FLAG_debug_code) { | 2037 if (emit_debug_code()) { |
| 2002 movq(kScratchRegister, | 2038 movq(kScratchRegister, |
| 2003 FACTORY->undefined_value(), | 2039 FACTORY->undefined_value(), |
| 2004 RelocInfo::EMBEDDED_OBJECT); | 2040 RelocInfo::EMBEDDED_OBJECT); |
| 2005 cmpq(Operand(rsp, 0), kScratchRegister); | 2041 cmpq(Operand(rsp, 0), kScratchRegister); |
| 2006 Check(not_equal, "code object not properly patched"); | 2042 Check(not_equal, "code object not properly patched"); |
| 2007 } | 2043 } |
| 2008 } | 2044 } |
| 2009 | 2045 |
| 2010 | 2046 |
| 2011 void MacroAssembler::LeaveFrame(StackFrame::Type type) { | 2047 void MacroAssembler::LeaveFrame(StackFrame::Type type) { |
| 2012 if (FLAG_debug_code) { | 2048 if (emit_debug_code()) { |
| 2013 Move(kScratchRegister, Smi::FromInt(type)); | 2049 Move(kScratchRegister, Smi::FromInt(type)); |
| 2014 cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister); | 2050 cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister); |
| 2015 Check(equal, "stack frame types must match"); | 2051 Check(equal, "stack frame types must match"); |
| 2016 } | 2052 } |
| 2017 movq(rsp, rbp); | 2053 movq(rsp, rbp); |
| 2018 pop(rbp); | 2054 pop(rbp); |
| 2019 } | 2055 } |
| 2020 | 2056 |
| 2021 | 2057 |
| 2022 void MacroAssembler::EnterExitFramePrologue(bool save_rax) { | 2058 void MacroAssembler::EnterExitFramePrologue(bool save_rax) { |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2152 Register scratch, | 2188 Register scratch, |
| 2153 Label* miss) { | 2189 Label* miss) { |
| 2154 Label same_contexts; | 2190 Label same_contexts; |
| 2155 | 2191 |
| 2156 ASSERT(!holder_reg.is(scratch)); | 2192 ASSERT(!holder_reg.is(scratch)); |
| 2157 ASSERT(!scratch.is(kScratchRegister)); | 2193 ASSERT(!scratch.is(kScratchRegister)); |
| 2158 // Load current lexical context from the stack frame. | 2194 // Load current lexical context from the stack frame. |
| 2159 movq(scratch, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2195 movq(scratch, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2160 | 2196 |
| 2161 // When generating debug code, make sure the lexical context is set. | 2197 // When generating debug code, make sure the lexical context is set. |
| 2162 if (FLAG_debug_code) { | 2198 if (emit_debug_code()) { |
| 2163 cmpq(scratch, Immediate(0)); | 2199 cmpq(scratch, Immediate(0)); |
| 2164 Check(not_equal, "we should not have an empty lexical context"); | 2200 Check(not_equal, "we should not have an empty lexical context"); |
| 2165 } | 2201 } |
| 2166 // Load the global context of the current context. | 2202 // Load the global context of the current context. |
| 2167 int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; | 2203 int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; |
| 2168 movq(scratch, FieldOperand(scratch, offset)); | 2204 movq(scratch, FieldOperand(scratch, offset)); |
| 2169 movq(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset)); | 2205 movq(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset)); |
| 2170 | 2206 |
| 2171 // Check the context is a global context. | 2207 // Check the context is a global context. |
| 2172 if (FLAG_debug_code) { | 2208 if (emit_debug_code()) { |
| 2173 Cmp(FieldOperand(scratch, HeapObject::kMapOffset), | 2209 Cmp(FieldOperand(scratch, HeapObject::kMapOffset), |
| 2174 FACTORY->global_context_map()); | 2210 FACTORY->global_context_map()); |
| 2175 Check(equal, "JSGlobalObject::global_context should be a global context."); | 2211 Check(equal, "JSGlobalObject::global_context should be a global context."); |
| 2176 } | 2212 } |
| 2177 | 2213 |
| 2178 // Check if both contexts are the same. | 2214 // Check if both contexts are the same. |
| 2179 cmpq(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); | 2215 cmpq(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); |
| 2180 j(equal, &same_contexts); | 2216 j(equal, &same_contexts); |
| 2181 | 2217 |
| 2182 // Compare security tokens. | 2218 // Compare security tokens. |
| 2183 // Check that the security token in the calling global object is | 2219 // Check that the security token in the calling global object is |
| 2184 // compatible with the security token in the receiving global | 2220 // compatible with the security token in the receiving global |
| 2185 // object. | 2221 // object. |
| 2186 | 2222 |
| 2187 // Check the context is a global context. | 2223 // Check the context is a global context. |
| 2188 if (FLAG_debug_code) { | 2224 if (emit_debug_code()) { |
| 2189 // Preserve original value of holder_reg. | 2225 // Preserve original value of holder_reg. |
| 2190 push(holder_reg); | 2226 push(holder_reg); |
| 2191 movq(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); | 2227 movq(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); |
| 2192 CompareRoot(holder_reg, Heap::kNullValueRootIndex); | 2228 CompareRoot(holder_reg, Heap::kNullValueRootIndex); |
| 2193 Check(not_equal, "JSGlobalProxy::context() should not be null."); | 2229 Check(not_equal, "JSGlobalProxy::context() should not be null."); |
| 2194 | 2230 |
| 2195 // Read the first word and compare to global_context_map(), | 2231 // Read the first word and compare to global_context_map(), |
| 2196 movq(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset)); | 2232 movq(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset)); |
| 2197 CompareRoot(holder_reg, Heap::kGlobalContextMapRootIndex); | 2233 CompareRoot(holder_reg, Heap::kGlobalContextMapRootIndex); |
| 2198 Check(equal, "JSGlobalObject::global_context should be a global context."); | 2234 Check(equal, "JSGlobalObject::global_context should be a global context."); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2239 load_rax(new_space_allocation_top); | 2275 load_rax(new_space_allocation_top); |
| 2240 } else { | 2276 } else { |
| 2241 movq(kScratchRegister, new_space_allocation_top); | 2277 movq(kScratchRegister, new_space_allocation_top); |
| 2242 movq(result, Operand(kScratchRegister, 0)); | 2278 movq(result, Operand(kScratchRegister, 0)); |
| 2243 } | 2279 } |
| 2244 } | 2280 } |
| 2245 | 2281 |
| 2246 | 2282 |
| 2247 void MacroAssembler::UpdateAllocationTopHelper(Register result_end, | 2283 void MacroAssembler::UpdateAllocationTopHelper(Register result_end, |
| 2248 Register scratch) { | 2284 Register scratch) { |
| 2249 if (FLAG_debug_code) { | 2285 if (emit_debug_code()) { |
| 2250 testq(result_end, Immediate(kObjectAlignmentMask)); | 2286 testq(result_end, Immediate(kObjectAlignmentMask)); |
| 2251 Check(zero, "Unaligned allocation in new space"); | 2287 Check(zero, "Unaligned allocation in new space"); |
| 2252 } | 2288 } |
| 2253 | 2289 |
| 2254 ExternalReference new_space_allocation_top = | 2290 ExternalReference new_space_allocation_top = |
| 2255 ExternalReference::new_space_allocation_top_address(); | 2291 ExternalReference::new_space_allocation_top_address(); |
| 2256 | 2292 |
| 2257 // Update new top. | 2293 // Update new top. |
| 2258 if (result_end.is(rax)) { | 2294 if (result_end.is(rax)) { |
| 2259 // rax can be stored directly to a memory location. | 2295 // rax can be stored directly to a memory location. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2270 } | 2306 } |
| 2271 | 2307 |
| 2272 | 2308 |
| 2273 void MacroAssembler::AllocateInNewSpace(int object_size, | 2309 void MacroAssembler::AllocateInNewSpace(int object_size, |
| 2274 Register result, | 2310 Register result, |
| 2275 Register result_end, | 2311 Register result_end, |
| 2276 Register scratch, | 2312 Register scratch, |
| 2277 Label* gc_required, | 2313 Label* gc_required, |
| 2278 AllocationFlags flags) { | 2314 AllocationFlags flags) { |
| 2279 if (!FLAG_inline_new) { | 2315 if (!FLAG_inline_new) { |
| 2280 if (FLAG_debug_code) { | 2316 if (emit_debug_code()) { |
| 2281 // Trash the registers to simulate an allocation failure. | 2317 // Trash the registers to simulate an allocation failure. |
| 2282 movl(result, Immediate(0x7091)); | 2318 movl(result, Immediate(0x7091)); |
| 2283 if (result_end.is_valid()) { | 2319 if (result_end.is_valid()) { |
| 2284 movl(result_end, Immediate(0x7191)); | 2320 movl(result_end, Immediate(0x7191)); |
| 2285 } | 2321 } |
| 2286 if (scratch.is_valid()) { | 2322 if (scratch.is_valid()) { |
| 2287 movl(scratch, Immediate(0x7291)); | 2323 movl(scratch, Immediate(0x7291)); |
| 2288 } | 2324 } |
| 2289 } | 2325 } |
| 2290 jmp(gc_required); | 2326 jmp(gc_required); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2328 | 2364 |
| 2329 void MacroAssembler::AllocateInNewSpace(int header_size, | 2365 void MacroAssembler::AllocateInNewSpace(int header_size, |
| 2330 ScaleFactor element_size, | 2366 ScaleFactor element_size, |
| 2331 Register element_count, | 2367 Register element_count, |
| 2332 Register result, | 2368 Register result, |
| 2333 Register result_end, | 2369 Register result_end, |
| 2334 Register scratch, | 2370 Register scratch, |
| 2335 Label* gc_required, | 2371 Label* gc_required, |
| 2336 AllocationFlags flags) { | 2372 AllocationFlags flags) { |
| 2337 if (!FLAG_inline_new) { | 2373 if (!FLAG_inline_new) { |
| 2338 if (FLAG_debug_code) { | 2374 if (emit_debug_code()) { |
| 2339 // Trash the registers to simulate an allocation failure. | 2375 // Trash the registers to simulate an allocation failure. |
| 2340 movl(result, Immediate(0x7091)); | 2376 movl(result, Immediate(0x7091)); |
| 2341 movl(result_end, Immediate(0x7191)); | 2377 movl(result_end, Immediate(0x7191)); |
| 2342 if (scratch.is_valid()) { | 2378 if (scratch.is_valid()) { |
| 2343 movl(scratch, Immediate(0x7291)); | 2379 movl(scratch, Immediate(0x7291)); |
| 2344 } | 2380 } |
| 2345 // Register element_count is not modified by the function. | 2381 // Register element_count is not modified by the function. |
| 2346 } | 2382 } |
| 2347 jmp(gc_required); | 2383 jmp(gc_required); |
| 2348 return; | 2384 return; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2375 } | 2411 } |
| 2376 | 2412 |
| 2377 | 2413 |
| 2378 void MacroAssembler::AllocateInNewSpace(Register object_size, | 2414 void MacroAssembler::AllocateInNewSpace(Register object_size, |
| 2379 Register result, | 2415 Register result, |
| 2380 Register result_end, | 2416 Register result_end, |
| 2381 Register scratch, | 2417 Register scratch, |
| 2382 Label* gc_required, | 2418 Label* gc_required, |
| 2383 AllocationFlags flags) { | 2419 AllocationFlags flags) { |
| 2384 if (!FLAG_inline_new) { | 2420 if (!FLAG_inline_new) { |
| 2385 if (FLAG_debug_code) { | 2421 if (emit_debug_code()) { |
| 2386 // Trash the registers to simulate an allocation failure. | 2422 // Trash the registers to simulate an allocation failure. |
| 2387 movl(result, Immediate(0x7091)); | 2423 movl(result, Immediate(0x7091)); |
| 2388 movl(result_end, Immediate(0x7191)); | 2424 movl(result_end, Immediate(0x7191)); |
| 2389 if (scratch.is_valid()) { | 2425 if (scratch.is_valid()) { |
| 2390 movl(scratch, Immediate(0x7291)); | 2426 movl(scratch, Immediate(0x7291)); |
| 2391 } | 2427 } |
| 2392 // object_size is left unchanged by this function. | 2428 // object_size is left unchanged by this function. |
| 2393 } | 2429 } |
| 2394 jmp(gc_required); | 2430 jmp(gc_required); |
| 2395 return; | 2431 return; |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2582 // Slot is in the current function context. Move it into the | 2618 // Slot is in the current function context. Move it into the |
| 2583 // destination register in case we store into it (the write barrier | 2619 // destination register in case we store into it (the write barrier |
| 2584 // cannot be allowed to destroy the context in rsi). | 2620 // cannot be allowed to destroy the context in rsi). |
| 2585 movq(dst, rsi); | 2621 movq(dst, rsi); |
| 2586 } | 2622 } |
| 2587 | 2623 |
| 2588 // We should not have found a 'with' context by walking the context chain | 2624 // We should not have found a 'with' context by walking the context chain |
| 2589 // (i.e., the static scope chain and runtime context chain do not agree). | 2625 // (i.e., the static scope chain and runtime context chain do not agree). |
| 2590 // A variable occurring in such a scope should have slot type LOOKUP and | 2626 // A variable occurring in such a scope should have slot type LOOKUP and |
| 2591 // not CONTEXT. | 2627 // not CONTEXT. |
| 2592 if (FLAG_debug_code) { | 2628 if (emit_debug_code()) { |
| 2593 cmpq(dst, Operand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX))); | 2629 cmpq(dst, Operand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX))); |
| 2594 Check(equal, "Yo dawg, I heard you liked function contexts " | 2630 Check(equal, "Yo dawg, I heard you liked function contexts " |
| 2595 "so I put function contexts in all your contexts"); | 2631 "so I put function contexts in all your contexts"); |
| 2596 } | 2632 } |
| 2597 } | 2633 } |
| 2598 | 2634 |
| 2599 #ifdef _WIN64 | 2635 #ifdef _WIN64 |
| 2600 static const int kRegisterPassedArguments = 4; | 2636 static const int kRegisterPassedArguments = 4; |
| 2601 #else | 2637 #else |
| 2602 static const int kRegisterPassedArguments = 6; | 2638 static const int kRegisterPassedArguments = 6; |
| 2603 #endif | 2639 #endif |
| 2604 | 2640 |
| 2605 void MacroAssembler::LoadGlobalFunction(int index, Register function) { | 2641 void MacroAssembler::LoadGlobalFunction(int index, Register function) { |
| 2606 // Load the global or builtins object from the current context. | 2642 // Load the global or builtins object from the current context. |
| 2607 movq(function, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); | 2643 movq(function, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 2608 // Load the global context from the global or builtins object. | 2644 // Load the global context from the global or builtins object. |
| 2609 movq(function, FieldOperand(function, GlobalObject::kGlobalContextOffset)); | 2645 movq(function, FieldOperand(function, GlobalObject::kGlobalContextOffset)); |
| 2610 // Load the function from the global context. | 2646 // Load the function from the global context. |
| 2611 movq(function, Operand(function, Context::SlotOffset(index))); | 2647 movq(function, Operand(function, Context::SlotOffset(index))); |
| 2612 } | 2648 } |
| 2613 | 2649 |
| 2614 | 2650 |
| 2615 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, | 2651 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, |
| 2616 Register map) { | 2652 Register map) { |
| 2617 // Load the initial map. The global functions all have initial maps. | 2653 // Load the initial map. The global functions all have initial maps. |
| 2618 movq(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 2654 movq(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
| 2619 if (FLAG_debug_code) { | 2655 if (emit_debug_code()) { |
| 2620 Label ok, fail; | 2656 Label ok, fail; |
| 2621 CheckMap(map, FACTORY->meta_map(), &fail, false); | 2657 CheckMap(map, FACTORY->meta_map(), &fail, false); |
| 2622 jmp(&ok); | 2658 jmp(&ok); |
| 2623 bind(&fail); | 2659 bind(&fail); |
| 2624 Abort("Global functions must have initial map"); | 2660 Abort("Global functions must have initial map"); |
| 2625 bind(&ok); | 2661 bind(&ok); |
| 2626 } | 2662 } |
| 2627 } | 2663 } |
| 2628 | 2664 |
| 2629 | 2665 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2687 } else { | 2723 } else { |
| 2688 // Push Isolate pointer after all parameters. | 2724 // Push Isolate pointer after all parameters. |
| 2689 int argument_slots_on_stack = | 2725 int argument_slots_on_stack = |
| 2690 ArgumentStackSlotsForCFunctionCall(num_arguments); | 2726 ArgumentStackSlotsForCFunctionCall(num_arguments); |
| 2691 movq(kScratchRegister, ExternalReference::isolate_address()); | 2727 movq(kScratchRegister, ExternalReference::isolate_address()); |
| 2692 movq(Operand(rsp, argument_slots_on_stack * kPointerSize), | 2728 movq(Operand(rsp, argument_slots_on_stack * kPointerSize), |
| 2693 kScratchRegister); | 2729 kScratchRegister); |
| 2694 } | 2730 } |
| 2695 | 2731 |
| 2696 // Check stack alignment. | 2732 // Check stack alignment. |
| 2697 if (FLAG_debug_code) { | 2733 if (emit_debug_code()) { |
| 2698 CheckStackAlignment(); | 2734 CheckStackAlignment(); |
| 2699 } | 2735 } |
| 2700 | 2736 |
| 2701 call(function); | 2737 call(function); |
| 2702 ASSERT(OS::ActivationFrameAlignment() != 0); | 2738 ASSERT(OS::ActivationFrameAlignment() != 0); |
| 2703 ASSERT(num_arguments >= 0); | 2739 ASSERT(num_arguments >= 0); |
| 2704 num_arguments += 1; | 2740 num_arguments += 1; |
| 2705 int argument_slots_on_stack = | 2741 int argument_slots_on_stack = |
| 2706 ArgumentStackSlotsForCFunctionCall(num_arguments); | 2742 ArgumentStackSlotsForCFunctionCall(num_arguments); |
| 2707 movq(rsp, Operand(rsp, argument_slots_on_stack * kPointerSize)); | 2743 movq(rsp, Operand(rsp, argument_slots_on_stack * kPointerSize)); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2722 CPU::FlushICache(address_, size_); | 2758 CPU::FlushICache(address_, size_); |
| 2723 | 2759 |
| 2724 // Check that the code was patched as expected. | 2760 // Check that the code was patched as expected. |
| 2725 ASSERT(masm_.pc_ == address_ + size_); | 2761 ASSERT(masm_.pc_ == address_ + size_); |
| 2726 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 2762 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
| 2727 } | 2763 } |
| 2728 | 2764 |
| 2729 } } // namespace v8::internal | 2765 } } // namespace v8::internal |
| 2730 | 2766 |
| 2731 #endif // V8_TARGET_ARCH_X64 | 2767 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |