| 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 23 matching lines...) Expand all Loading... |
| 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 the young generation. | 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 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 700 return kScratchRegister; | 700 return kScratchRegister; |
| 701 } | 701 } |
| 702 if (value == 1) { | 702 if (value == 1) { |
| 703 return kSmiConstantRegister; | 703 return kSmiConstantRegister; |
| 704 } | 704 } |
| 705 LoadSmiConstant(kScratchRegister, source); | 705 LoadSmiConstant(kScratchRegister, source); |
| 706 return kScratchRegister; | 706 return kScratchRegister; |
| 707 } | 707 } |
| 708 | 708 |
| 709 void MacroAssembler::LoadSmiConstant(Register dst, Smi* source) { | 709 void MacroAssembler::LoadSmiConstant(Register dst, Smi* source) { |
| 710 if (FLAG_debug_code) { | 710 if (emit_debug_code()) { |
| 711 movq(dst, | 711 movq(dst, |
| 712 reinterpret_cast<uint64_t>(Smi::FromInt(kSmiConstantRegisterValue)), | 712 reinterpret_cast<uint64_t>(Smi::FromInt(kSmiConstantRegisterValue)), |
| 713 RelocInfo::NONE); | 713 RelocInfo::NONE); |
| 714 cmpq(dst, kSmiConstantRegister); | 714 cmpq(dst, kSmiConstantRegister); |
| 715 if (allow_stub_calls()) { | 715 if (allow_stub_calls()) { |
| 716 Assert(equal, "Uninitialized kSmiConstantRegister"); | 716 Assert(equal, "Uninitialized kSmiConstantRegister"); |
| 717 } else { | 717 } else { |
| 718 NearLabel ok; | 718 NearLabel ok; |
| 719 j(equal, &ok); | 719 j(equal, &ok); |
| 720 int3(); | 720 int3(); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 769 void MacroAssembler::Integer32ToSmi(Register dst, Register src) { | 769 void MacroAssembler::Integer32ToSmi(Register dst, Register src) { |
| 770 ASSERT_EQ(0, kSmiTag); | 770 ASSERT_EQ(0, kSmiTag); |
| 771 if (!dst.is(src)) { | 771 if (!dst.is(src)) { |
| 772 movl(dst, src); | 772 movl(dst, src); |
| 773 } | 773 } |
| 774 shl(dst, Immediate(kSmiShift)); | 774 shl(dst, Immediate(kSmiShift)); |
| 775 } | 775 } |
| 776 | 776 |
| 777 | 777 |
| 778 void MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) { | 778 void MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) { |
| 779 if (FLAG_debug_code) { | 779 if (emit_debug_code()) { |
| 780 testb(dst, Immediate(0x01)); | 780 testb(dst, Immediate(0x01)); |
| 781 NearLabel ok; | 781 NearLabel ok; |
| 782 j(zero, &ok); | 782 j(zero, &ok); |
| 783 if (allow_stub_calls()) { | 783 if (allow_stub_calls()) { |
| 784 Abort("Integer32ToSmiField writing to non-smi location"); | 784 Abort("Integer32ToSmiField writing to non-smi location"); |
| 785 } else { | 785 } else { |
| 786 int3(); | 786 int3(); |
| 787 } | 787 } |
| 788 bind(&ok); | 788 bind(&ok); |
| 789 } | 789 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 831 movsxlq(dst, Operand(src, kSmiShift / kBitsPerByte)); | 831 movsxlq(dst, Operand(src, kSmiShift / kBitsPerByte)); |
| 832 } | 832 } |
| 833 | 833 |
| 834 | 834 |
| 835 void MacroAssembler::SmiTest(Register src) { | 835 void MacroAssembler::SmiTest(Register src) { |
| 836 testq(src, src); | 836 testq(src, src); |
| 837 } | 837 } |
| 838 | 838 |
| 839 | 839 |
| 840 void MacroAssembler::SmiCompare(Register smi1, Register smi2) { | 840 void MacroAssembler::SmiCompare(Register smi1, Register smi2) { |
| 841 if (FLAG_debug_code) { | 841 if (emit_debug_code()) { |
| 842 AbortIfNotSmi(smi1); | 842 AbortIfNotSmi(smi1); |
| 843 AbortIfNotSmi(smi2); | 843 AbortIfNotSmi(smi2); |
| 844 } | 844 } |
| 845 cmpq(smi1, smi2); | 845 cmpq(smi1, smi2); |
| 846 } | 846 } |
| 847 | 847 |
| 848 | 848 |
| 849 void MacroAssembler::SmiCompare(Register dst, Smi* src) { | 849 void MacroAssembler::SmiCompare(Register dst, Smi* src) { |
| 850 if (FLAG_debug_code) { | 850 if (emit_debug_code()) { |
| 851 AbortIfNotSmi(dst); | 851 AbortIfNotSmi(dst); |
| 852 } | 852 } |
| 853 Cmp(dst, src); | 853 Cmp(dst, src); |
| 854 } | 854 } |
| 855 | 855 |
| 856 | 856 |
| 857 void MacroAssembler::Cmp(Register dst, Smi* src) { | 857 void MacroAssembler::Cmp(Register dst, Smi* src) { |
| 858 ASSERT(!dst.is(kScratchRegister)); | 858 ASSERT(!dst.is(kScratchRegister)); |
| 859 if (src->value() == 0) { | 859 if (src->value() == 0) { |
| 860 testq(dst, dst); | 860 testq(dst, dst); |
| 861 } else { | 861 } else { |
| 862 Register constant_reg = GetSmiConstant(src); | 862 Register constant_reg = GetSmiConstant(src); |
| 863 cmpq(dst, constant_reg); | 863 cmpq(dst, constant_reg); |
| 864 } | 864 } |
| 865 } | 865 } |
| 866 | 866 |
| 867 | 867 |
| 868 void MacroAssembler::SmiCompare(Register dst, const Operand& src) { | 868 void MacroAssembler::SmiCompare(Register dst, const Operand& src) { |
| 869 if (FLAG_debug_code) { | 869 if (emit_debug_code()) { |
| 870 AbortIfNotSmi(dst); | 870 AbortIfNotSmi(dst); |
| 871 AbortIfNotSmi(src); | 871 AbortIfNotSmi(src); |
| 872 } | 872 } |
| 873 cmpq(dst, src); | 873 cmpq(dst, src); |
| 874 } | 874 } |
| 875 | 875 |
| 876 | 876 |
| 877 void MacroAssembler::SmiCompare(const Operand& dst, Register src) { | 877 void MacroAssembler::SmiCompare(const Operand& dst, Register src) { |
| 878 if (FLAG_debug_code) { | 878 if (emit_debug_code()) { |
| 879 AbortIfNotSmi(dst); | 879 AbortIfNotSmi(dst); |
| 880 AbortIfNotSmi(src); | 880 AbortIfNotSmi(src); |
| 881 } | 881 } |
| 882 cmpq(dst, src); | 882 cmpq(dst, src); |
| 883 } | 883 } |
| 884 | 884 |
| 885 | 885 |
| 886 void MacroAssembler::SmiCompare(const Operand& dst, Smi* src) { | 886 void MacroAssembler::SmiCompare(const Operand& dst, Smi* src) { |
| 887 if (FLAG_debug_code) { | 887 if (emit_debug_code()) { |
| 888 AbortIfNotSmi(dst); | 888 AbortIfNotSmi(dst); |
| 889 } | 889 } |
| 890 cmpl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(src->value())); | 890 cmpl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(src->value())); |
| 891 } | 891 } |
| 892 | 892 |
| 893 | 893 |
| 894 void MacroAssembler::Cmp(const Operand& dst, Smi* src) { | 894 void MacroAssembler::Cmp(const Operand& dst, Smi* src) { |
| 895 // The Operand cannot use the smi register. | 895 // The Operand cannot use the smi register. |
| 896 Register smi_reg = GetSmiConstant(src); | 896 Register smi_reg = GetSmiConstant(src); |
| 897 ASSERT(!dst.AddressUsesRegister(smi_reg)); | 897 ASSERT(!dst.AddressUsesRegister(smi_reg)); |
| (...skipping 1122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2020 } | 2020 } |
| 2021 | 2021 |
| 2022 | 2022 |
| 2023 void MacroAssembler::EnterFrame(StackFrame::Type type) { | 2023 void MacroAssembler::EnterFrame(StackFrame::Type type) { |
| 2024 push(rbp); | 2024 push(rbp); |
| 2025 movq(rbp, rsp); | 2025 movq(rbp, rsp); |
| 2026 push(rsi); // Context. | 2026 push(rsi); // Context. |
| 2027 Push(Smi::FromInt(type)); | 2027 Push(Smi::FromInt(type)); |
| 2028 movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); | 2028 movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); |
| 2029 push(kScratchRegister); | 2029 push(kScratchRegister); |
| 2030 if (FLAG_debug_code) { | 2030 if (emit_debug_code()) { |
| 2031 movq(kScratchRegister, | 2031 movq(kScratchRegister, |
| 2032 Factory::undefined_value(), | 2032 Factory::undefined_value(), |
| 2033 RelocInfo::EMBEDDED_OBJECT); | 2033 RelocInfo::EMBEDDED_OBJECT); |
| 2034 cmpq(Operand(rsp, 0), kScratchRegister); | 2034 cmpq(Operand(rsp, 0), kScratchRegister); |
| 2035 Check(not_equal, "code object not properly patched"); | 2035 Check(not_equal, "code object not properly patched"); |
| 2036 } | 2036 } |
| 2037 } | 2037 } |
| 2038 | 2038 |
| 2039 | 2039 |
| 2040 void MacroAssembler::LeaveFrame(StackFrame::Type type) { | 2040 void MacroAssembler::LeaveFrame(StackFrame::Type type) { |
| 2041 if (FLAG_debug_code) { | 2041 if (emit_debug_code()) { |
| 2042 Move(kScratchRegister, Smi::FromInt(type)); | 2042 Move(kScratchRegister, Smi::FromInt(type)); |
| 2043 cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister); | 2043 cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister); |
| 2044 Check(equal, "stack frame types must match"); | 2044 Check(equal, "stack frame types must match"); |
| 2045 } | 2045 } |
| 2046 movq(rsp, rbp); | 2046 movq(rsp, rbp); |
| 2047 pop(rbp); | 2047 pop(rbp); |
| 2048 } | 2048 } |
| 2049 | 2049 |
| 2050 | 2050 |
| 2051 void MacroAssembler::EnterExitFramePrologue(bool save_rax) { | 2051 void MacroAssembler::EnterExitFramePrologue(bool save_rax) { |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2181 Register scratch, | 2181 Register scratch, |
| 2182 Label* miss) { | 2182 Label* miss) { |
| 2183 Label same_contexts; | 2183 Label same_contexts; |
| 2184 | 2184 |
| 2185 ASSERT(!holder_reg.is(scratch)); | 2185 ASSERT(!holder_reg.is(scratch)); |
| 2186 ASSERT(!scratch.is(kScratchRegister)); | 2186 ASSERT(!scratch.is(kScratchRegister)); |
| 2187 // Load current lexical context from the stack frame. | 2187 // Load current lexical context from the stack frame. |
| 2188 movq(scratch, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2188 movq(scratch, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2189 | 2189 |
| 2190 // When generating debug code, make sure the lexical context is set. | 2190 // When generating debug code, make sure the lexical context is set. |
| 2191 if (FLAG_debug_code) { | 2191 if (emit_debug_code()) { |
| 2192 cmpq(scratch, Immediate(0)); | 2192 cmpq(scratch, Immediate(0)); |
| 2193 Check(not_equal, "we should not have an empty lexical context"); | 2193 Check(not_equal, "we should not have an empty lexical context"); |
| 2194 } | 2194 } |
| 2195 // Load the global context of the current context. | 2195 // Load the global context of the current context. |
| 2196 int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; | 2196 int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; |
| 2197 movq(scratch, FieldOperand(scratch, offset)); | 2197 movq(scratch, FieldOperand(scratch, offset)); |
| 2198 movq(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset)); | 2198 movq(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset)); |
| 2199 | 2199 |
| 2200 // Check the context is a global context. | 2200 // Check the context is a global context. |
| 2201 if (FLAG_debug_code) { | 2201 if (emit_debug_code()) { |
| 2202 Cmp(FieldOperand(scratch, HeapObject::kMapOffset), | 2202 Cmp(FieldOperand(scratch, HeapObject::kMapOffset), |
| 2203 Factory::global_context_map()); | 2203 Factory::global_context_map()); |
| 2204 Check(equal, "JSGlobalObject::global_context should be a global context."); | 2204 Check(equal, "JSGlobalObject::global_context should be a global context."); |
| 2205 } | 2205 } |
| 2206 | 2206 |
| 2207 // Check if both contexts are the same. | 2207 // Check if both contexts are the same. |
| 2208 cmpq(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); | 2208 cmpq(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); |
| 2209 j(equal, &same_contexts); | 2209 j(equal, &same_contexts); |
| 2210 | 2210 |
| 2211 // Compare security tokens. | 2211 // Compare security tokens. |
| 2212 // Check that the security token in the calling global object is | 2212 // Check that the security token in the calling global object is |
| 2213 // compatible with the security token in the receiving global | 2213 // compatible with the security token in the receiving global |
| 2214 // object. | 2214 // object. |
| 2215 | 2215 |
| 2216 // Check the context is a global context. | 2216 // Check the context is a global context. |
| 2217 if (FLAG_debug_code) { | 2217 if (emit_debug_code()) { |
| 2218 // Preserve original value of holder_reg. | 2218 // Preserve original value of holder_reg. |
| 2219 push(holder_reg); | 2219 push(holder_reg); |
| 2220 movq(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); | 2220 movq(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset)); |
| 2221 CompareRoot(holder_reg, Heap::kNullValueRootIndex); | 2221 CompareRoot(holder_reg, Heap::kNullValueRootIndex); |
| 2222 Check(not_equal, "JSGlobalProxy::context() should not be null."); | 2222 Check(not_equal, "JSGlobalProxy::context() should not be null."); |
| 2223 | 2223 |
| 2224 // Read the first word and compare to global_context_map(), | 2224 // Read the first word and compare to global_context_map(), |
| 2225 movq(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset)); | 2225 movq(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset)); |
| 2226 CompareRoot(holder_reg, Heap::kGlobalContextMapRootIndex); | 2226 CompareRoot(holder_reg, Heap::kGlobalContextMapRootIndex); |
| 2227 Check(equal, "JSGlobalObject::global_context should be a global context."); | 2227 Check(equal, "JSGlobalObject::global_context should be a global context."); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2268 load_rax(new_space_allocation_top); | 2268 load_rax(new_space_allocation_top); |
| 2269 } else { | 2269 } else { |
| 2270 movq(kScratchRegister, new_space_allocation_top); | 2270 movq(kScratchRegister, new_space_allocation_top); |
| 2271 movq(result, Operand(kScratchRegister, 0)); | 2271 movq(result, Operand(kScratchRegister, 0)); |
| 2272 } | 2272 } |
| 2273 } | 2273 } |
| 2274 | 2274 |
| 2275 | 2275 |
| 2276 void MacroAssembler::UpdateAllocationTopHelper(Register result_end, | 2276 void MacroAssembler::UpdateAllocationTopHelper(Register result_end, |
| 2277 Register scratch) { | 2277 Register scratch) { |
| 2278 if (FLAG_debug_code) { | 2278 if (emit_debug_code()) { |
| 2279 testq(result_end, Immediate(kObjectAlignmentMask)); | 2279 testq(result_end, Immediate(kObjectAlignmentMask)); |
| 2280 Check(zero, "Unaligned allocation in new space"); | 2280 Check(zero, "Unaligned allocation in new space"); |
| 2281 } | 2281 } |
| 2282 | 2282 |
| 2283 ExternalReference new_space_allocation_top = | 2283 ExternalReference new_space_allocation_top = |
| 2284 ExternalReference::new_space_allocation_top_address(); | 2284 ExternalReference::new_space_allocation_top_address(); |
| 2285 | 2285 |
| 2286 // Update new top. | 2286 // Update new top. |
| 2287 if (result_end.is(rax)) { | 2287 if (result_end.is(rax)) { |
| 2288 // rax can be stored directly to a memory location. | 2288 // rax can be stored directly to a memory location. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2299 } | 2299 } |
| 2300 | 2300 |
| 2301 | 2301 |
| 2302 void MacroAssembler::AllocateInNewSpace(int object_size, | 2302 void MacroAssembler::AllocateInNewSpace(int object_size, |
| 2303 Register result, | 2303 Register result, |
| 2304 Register result_end, | 2304 Register result_end, |
| 2305 Register scratch, | 2305 Register scratch, |
| 2306 Label* gc_required, | 2306 Label* gc_required, |
| 2307 AllocationFlags flags) { | 2307 AllocationFlags flags) { |
| 2308 if (!FLAG_inline_new) { | 2308 if (!FLAG_inline_new) { |
| 2309 if (FLAG_debug_code) { | 2309 if (emit_debug_code()) { |
| 2310 // Trash the registers to simulate an allocation failure. | 2310 // Trash the registers to simulate an allocation failure. |
| 2311 movl(result, Immediate(0x7091)); | 2311 movl(result, Immediate(0x7091)); |
| 2312 if (result_end.is_valid()) { | 2312 if (result_end.is_valid()) { |
| 2313 movl(result_end, Immediate(0x7191)); | 2313 movl(result_end, Immediate(0x7191)); |
| 2314 } | 2314 } |
| 2315 if (scratch.is_valid()) { | 2315 if (scratch.is_valid()) { |
| 2316 movl(scratch, Immediate(0x7291)); | 2316 movl(scratch, Immediate(0x7291)); |
| 2317 } | 2317 } |
| 2318 } | 2318 } |
| 2319 jmp(gc_required); | 2319 jmp(gc_required); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2357 | 2357 |
| 2358 void MacroAssembler::AllocateInNewSpace(int header_size, | 2358 void MacroAssembler::AllocateInNewSpace(int header_size, |
| 2359 ScaleFactor element_size, | 2359 ScaleFactor element_size, |
| 2360 Register element_count, | 2360 Register element_count, |
| 2361 Register result, | 2361 Register result, |
| 2362 Register result_end, | 2362 Register result_end, |
| 2363 Register scratch, | 2363 Register scratch, |
| 2364 Label* gc_required, | 2364 Label* gc_required, |
| 2365 AllocationFlags flags) { | 2365 AllocationFlags flags) { |
| 2366 if (!FLAG_inline_new) { | 2366 if (!FLAG_inline_new) { |
| 2367 if (FLAG_debug_code) { | 2367 if (emit_debug_code()) { |
| 2368 // Trash the registers to simulate an allocation failure. | 2368 // Trash the registers to simulate an allocation failure. |
| 2369 movl(result, Immediate(0x7091)); | 2369 movl(result, Immediate(0x7091)); |
| 2370 movl(result_end, Immediate(0x7191)); | 2370 movl(result_end, Immediate(0x7191)); |
| 2371 if (scratch.is_valid()) { | 2371 if (scratch.is_valid()) { |
| 2372 movl(scratch, Immediate(0x7291)); | 2372 movl(scratch, Immediate(0x7291)); |
| 2373 } | 2373 } |
| 2374 // Register element_count is not modified by the function. | 2374 // Register element_count is not modified by the function. |
| 2375 } | 2375 } |
| 2376 jmp(gc_required); | 2376 jmp(gc_required); |
| 2377 return; | 2377 return; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2404 } | 2404 } |
| 2405 | 2405 |
| 2406 | 2406 |
| 2407 void MacroAssembler::AllocateInNewSpace(Register object_size, | 2407 void MacroAssembler::AllocateInNewSpace(Register object_size, |
| 2408 Register result, | 2408 Register result, |
| 2409 Register result_end, | 2409 Register result_end, |
| 2410 Register scratch, | 2410 Register scratch, |
| 2411 Label* gc_required, | 2411 Label* gc_required, |
| 2412 AllocationFlags flags) { | 2412 AllocationFlags flags) { |
| 2413 if (!FLAG_inline_new) { | 2413 if (!FLAG_inline_new) { |
| 2414 if (FLAG_debug_code) { | 2414 if (emit_debug_code()) { |
| 2415 // Trash the registers to simulate an allocation failure. | 2415 // Trash the registers to simulate an allocation failure. |
| 2416 movl(result, Immediate(0x7091)); | 2416 movl(result, Immediate(0x7091)); |
| 2417 movl(result_end, Immediate(0x7191)); | 2417 movl(result_end, Immediate(0x7191)); |
| 2418 if (scratch.is_valid()) { | 2418 if (scratch.is_valid()) { |
| 2419 movl(scratch, Immediate(0x7291)); | 2419 movl(scratch, Immediate(0x7291)); |
| 2420 } | 2420 } |
| 2421 // object_size is left unchanged by this function. | 2421 // object_size is left unchanged by this function. |
| 2422 } | 2422 } |
| 2423 jmp(gc_required); | 2423 jmp(gc_required); |
| 2424 return; | 2424 return; |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2611 // Slot is in the current function context. Move it into the | 2611 // Slot is in the current function context. Move it into the |
| 2612 // destination register in case we store into it (the write barrier | 2612 // destination register in case we store into it (the write barrier |
| 2613 // cannot be allowed to destroy the context in rsi). | 2613 // cannot be allowed to destroy the context in rsi). |
| 2614 movq(dst, rsi); | 2614 movq(dst, rsi); |
| 2615 } | 2615 } |
| 2616 | 2616 |
| 2617 // We should not have found a 'with' context by walking the context chain | 2617 // We should not have found a 'with' context by walking the context chain |
| 2618 // (i.e., the static scope chain and runtime context chain do not agree). | 2618 // (i.e., the static scope chain and runtime context chain do not agree). |
| 2619 // A variable occurring in such a scope should have slot type LOOKUP and | 2619 // A variable occurring in such a scope should have slot type LOOKUP and |
| 2620 // not CONTEXT. | 2620 // not CONTEXT. |
| 2621 if (FLAG_debug_code) { | 2621 if (emit_debug_code()) { |
| 2622 cmpq(dst, Operand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX))); | 2622 cmpq(dst, Operand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX))); |
| 2623 Check(equal, "Yo dawg, I heard you liked function contexts " | 2623 Check(equal, "Yo dawg, I heard you liked function contexts " |
| 2624 "so I put function contexts in all your contexts"); | 2624 "so I put function contexts in all your contexts"); |
| 2625 } | 2625 } |
| 2626 } | 2626 } |
| 2627 | 2627 |
| 2628 | 2628 |
| 2629 void MacroAssembler::LoadGlobalFunction(int index, Register function) { | 2629 void MacroAssembler::LoadGlobalFunction(int index, Register function) { |
| 2630 // Load the global or builtins object from the current context. | 2630 // Load the global or builtins object from the current context. |
| 2631 movq(function, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); | 2631 movq(function, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 2632 // Load the global context from the global or builtins object. | 2632 // Load the global context from the global or builtins object. |
| 2633 movq(function, FieldOperand(function, GlobalObject::kGlobalContextOffset)); | 2633 movq(function, FieldOperand(function, GlobalObject::kGlobalContextOffset)); |
| 2634 // Load the function from the global context. | 2634 // Load the function from the global context. |
| 2635 movq(function, Operand(function, Context::SlotOffset(index))); | 2635 movq(function, Operand(function, Context::SlotOffset(index))); |
| 2636 } | 2636 } |
| 2637 | 2637 |
| 2638 | 2638 |
| 2639 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, | 2639 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, |
| 2640 Register map) { | 2640 Register map) { |
| 2641 // Load the initial map. The global functions all have initial maps. | 2641 // Load the initial map. The global functions all have initial maps. |
| 2642 movq(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 2642 movq(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
| 2643 if (FLAG_debug_code) { | 2643 if (emit_debug_code()) { |
| 2644 Label ok, fail; | 2644 Label ok, fail; |
| 2645 CheckMap(map, Factory::meta_map(), &fail, false); | 2645 CheckMap(map, Factory::meta_map(), &fail, false); |
| 2646 jmp(&ok); | 2646 jmp(&ok); |
| 2647 bind(&fail); | 2647 bind(&fail); |
| 2648 Abort("Global functions must have initial map"); | 2648 Abort("Global functions must have initial map"); |
| 2649 bind(&ok); | 2649 bind(&ok); |
| 2650 } | 2650 } |
| 2651 } | 2651 } |
| 2652 | 2652 |
| 2653 | 2653 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2688 | 2688 |
| 2689 void MacroAssembler::CallCFunction(ExternalReference function, | 2689 void MacroAssembler::CallCFunction(ExternalReference function, |
| 2690 int num_arguments) { | 2690 int num_arguments) { |
| 2691 movq(rax, function); | 2691 movq(rax, function); |
| 2692 CallCFunction(rax, num_arguments); | 2692 CallCFunction(rax, num_arguments); |
| 2693 } | 2693 } |
| 2694 | 2694 |
| 2695 | 2695 |
| 2696 void MacroAssembler::CallCFunction(Register function, int num_arguments) { | 2696 void MacroAssembler::CallCFunction(Register function, int num_arguments) { |
| 2697 // Check stack alignment. | 2697 // Check stack alignment. |
| 2698 if (FLAG_debug_code) { | 2698 if (emit_debug_code()) { |
| 2699 CheckStackAlignment(); | 2699 CheckStackAlignment(); |
| 2700 } | 2700 } |
| 2701 | 2701 |
| 2702 call(function); | 2702 call(function); |
| 2703 ASSERT(OS::ActivationFrameAlignment() != 0); | 2703 ASSERT(OS::ActivationFrameAlignment() != 0); |
| 2704 ASSERT(num_arguments >= 0); | 2704 ASSERT(num_arguments >= 0); |
| 2705 int argument_slots_on_stack = | 2705 int argument_slots_on_stack = |
| 2706 ArgumentStackSlotsForCFunctionCall(num_arguments); | 2706 ArgumentStackSlotsForCFunctionCall(num_arguments); |
| 2707 movq(rsp, Operand(rsp, argument_slots_on_stack * kPointerSize)); | 2707 movq(rsp, Operand(rsp, argument_slots_on_stack * kPointerSize)); |
| 2708 } | 2708 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2722 CPU::FlushICache(address_, size_); | 2722 CPU::FlushICache(address_, size_); |
| 2723 | 2723 |
| 2724 // Check that the code was patched as expected. | 2724 // Check that the code was patched as expected. |
| 2725 ASSERT(masm_.pc_ == address_ + size_); | 2725 ASSERT(masm_.pc_ == address_ + size_); |
| 2726 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 2726 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
| 2727 } | 2727 } |
| 2728 | 2728 |
| 2729 } } // namespace v8::internal | 2729 } } // namespace v8::internal |
| 2730 | 2730 |
| 2731 #endif // V8_TARGET_ARCH_X64 | 2731 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |