| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 void MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) { | 66 void MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) { |
| 67 cmpq(with, Operand(kRootRegister, index << kPointerSizeLog2)); | 67 cmpq(with, Operand(kRootRegister, index << kPointerSizeLog2)); |
| 68 } | 68 } |
| 69 | 69 |
| 70 | 70 |
| 71 void MacroAssembler::CompareRoot(Operand with, Heap::RootListIndex index) { | 71 void MacroAssembler::CompareRoot(Operand with, Heap::RootListIndex index) { |
| 72 LoadRoot(kScratchRegister, index); | 72 LoadRoot(kScratchRegister, index); |
| 73 cmpq(with, kScratchRegister); | 73 cmpq(with, kScratchRegister); |
| 74 } | 74 } |
| 75 | 75 |
| 76 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER | 76 |
| 77 void MacroAssembler::RecordWriteHelper(Register object, | 77 void MacroAssembler::RecordWriteHelper(Register object, |
| 78 Register addr, | 78 Register addr, |
| 79 Register scratch) { | 79 Register scratch, |
| 80 SaveFPRegsMode save_fp) { |
| 80 if (FLAG_debug_code) { | 81 if (FLAG_debug_code) { |
| 81 // Check that the object is not in new space. | 82 // Check that the object is not in new space. |
| 82 NearLabel not_in_new_space; | 83 NearLabel not_in_new_space; |
| 83 InNewSpace(object, scratch, not_equal, ¬_in_new_space); | 84 InNewSpace(object, scratch, not_equal, ¬_in_new_space); |
| 84 Abort("new-space object passed to RecordWriteHelper"); | 85 Abort("new-space object passed to RecordWriteHelper"); |
| 85 bind(¬_in_new_space); | 86 bind(¬_in_new_space); |
| 86 } | 87 } |
| 87 | 88 |
| 88 // Compute the page start address from the heap object pointer, and reuse | 89 // Load write buffer top. |
| 89 // the 'object' register for it. | 90 LoadRoot(scratch, Heap::kWriteBufferTopRootIndex); |
| 90 and_(object, Immediate(~Page::kPageAlignmentMask)); | 91 // Store pointer to buffer. |
| 91 | 92 movq(Operand(scratch, 0), addr); |
| 92 // Compute number of region covering addr. See Page::GetRegionNumberForAddress | 93 // Increment buffer top. |
| 93 // method for more details. | 94 addq(scratch, Immediate(kPointerSize)); |
| 94 shrl(addr, Immediate(Page::kRegionSizeLog2)); | 95 // Write back new top of buffer. |
| 95 andl(addr, Immediate(Page::kPageAlignmentMask >> Page::kRegionSizeLog2)); | 96 StoreRoot(scratch, Heap::kWriteBufferTopRootIndex); |
| 96 | 97 // Call stub on end of buffer. |
| 97 // Set dirty mark for region. | 98 NearLabel no_overflow; |
| 98 bts(Operand(object, Page::kDirtyFlagOffset), addr); | 99 // Check for end of buffer. |
| 100 testq(scratch, Immediate(WriteBuffer::kWriteBufferOverflowBit)); |
| 101 j(equal, &no_overflow); |
| 102 WriteBufferOverflowStub write_buffer_overflow = |
| 103 WriteBufferOverflowStub(save_fp); |
| 104 CallStub(&write_buffer_overflow); |
| 105 bind(&no_overflow); |
| 99 } | 106 } |
| 100 | 107 |
| 101 | 108 |
| 102 void MacroAssembler::RecordWrite(Register object, | 109 void MacroAssembler::RecordWrite(Register object, |
| 103 int offset, | 110 int offset, |
| 104 Register value, | 111 Register value, |
| 105 Register index) { | 112 Register index, |
| 113 SaveFPRegsMode save_fp) { |
| 106 // The compiled code assumes that record write doesn't change the | 114 // The compiled code assumes that record write doesn't change the |
| 107 // context register, so we check that none of the clobbered | 115 // context register, so we check that none of the clobbered |
| 108 // registers are rsi. | 116 // registers are rsi. |
| 109 ASSERT(!object.is(rsi) && !value.is(rsi) && !index.is(rsi)); | 117 ASSERT(!object.is(rsi) && !value.is(rsi) && !index.is(rsi)); |
| 110 | 118 |
| 111 // First, check if a write barrier is even needed. The tests below | 119 // First, check if a write barrier is even needed. The tests below |
| 112 // catch stores of Smis and stores into young gen. | 120 // catch stores of Smis and stores into young gen. |
| 113 Label done; | 121 Label done; |
| 114 JumpIfSmi(value, &done); | 122 JumpIfSmi(value, &done); |
| 115 | 123 |
| 116 RecordWriteNonSmi(object, offset, value, index); | 124 RecordWriteNonSmi(object, offset, value, index, save_fp); |
| 117 bind(&done); | 125 bind(&done); |
| 118 | 126 |
| 119 // Clobber all input registers when running with the debug-code flag | 127 // Clobber all input registers when running with the debug-code flag |
| 120 // turned on to provoke errors. This clobbering repeats the | 128 // turned on to provoke errors. This clobbering repeats the |
| 121 // clobbering done inside RecordWriteNonSmi but it's necessary to | 129 // clobbering done inside RecordWriteNonSmi but it's necessary to |
| 122 // avoid having the fast case for smis leave the registers | 130 // avoid having the fast case for smis leave the registers |
| 123 // unchanged. | 131 // unchanged. |
| 124 if (FLAG_debug_code) { | 132 if (FLAG_debug_code) { |
| 125 movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 133 movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 126 movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 134 movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 127 movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 135 movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 128 } | 136 } |
| 129 } | 137 } |
| 130 | 138 |
| 131 | 139 |
| 132 void MacroAssembler::RecordWrite(Register object, | 140 void MacroAssembler::RecordWrite(Register object, |
| 133 Register address, | 141 Register address, |
| 134 Register value) { | 142 Register value, |
| 143 SaveFPRegsMode save_fp) { |
| 135 // The compiled code assumes that record write doesn't change the | 144 // The compiled code assumes that record write doesn't change the |
| 136 // context register, so we check that none of the clobbered | 145 // context register, so we check that none of the clobbered |
| 137 // registers are esi. | 146 // registers are esi. |
| 138 ASSERT(!object.is(rsi) && !value.is(rsi) && !address.is(rsi)); | 147 ASSERT(!object.is(rsi) && !value.is(rsi) && !address.is(rsi)); |
| 139 | 148 |
| 140 // First, check if a write barrier is even needed. The tests below | 149 // First, check if a write barrier is even needed. The tests below |
| 141 // catch stores of Smis and stores into young gen. | 150 // catch stores of Smis and stores into young gen. |
| 142 Label done; | 151 Label done; |
| 143 JumpIfSmi(value, &done); | 152 JumpIfSmi(value, &done); |
| 144 | 153 |
| 145 InNewSpace(object, value, equal, &done); | 154 InNewSpace(object, value, equal, &done); |
| 146 | 155 |
| 147 RecordWriteHelper(object, address, value); | 156 RecordWriteHelper(object, address, value, save_fp); |
| 148 | 157 |
| 149 bind(&done); | 158 bind(&done); |
| 150 | 159 |
| 151 // Clobber all input registers when running with the debug-code flag | 160 // Clobber all input registers when running with the debug-code flag |
| 152 // turned on to provoke errors. | 161 // turned on to provoke errors. |
| 153 if (FLAG_debug_code) { | 162 if (FLAG_debug_code) { |
| 154 movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 163 movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 155 movq(address, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 164 movq(address, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 156 movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 165 movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 157 } | 166 } |
| 158 } | 167 } |
| 159 | 168 |
| 160 | 169 |
| 161 void MacroAssembler::RecordWriteNonSmi(Register object, | 170 void MacroAssembler::RecordWriteNonSmi(Register object, |
| 162 int offset, | 171 int offset, |
| 163 Register scratch, | 172 Register scratch, |
| 164 Register index) { | 173 Register index, |
| 174 SaveFPRegsMode save_fp) { |
| 165 Label done; | 175 Label done; |
| 166 | 176 |
| 167 if (FLAG_debug_code) { | 177 if (FLAG_debug_code) { |
| 168 NearLabel okay; | 178 NearLabel okay; |
| 169 JumpIfNotSmi(object, &okay); | 179 JumpIfNotSmi(object, &okay); |
| 170 Abort("MacroAssembler::RecordWriteNonSmi cannot deal with smis"); | 180 Abort("MacroAssembler::RecordWriteNonSmi cannot deal with smis"); |
| 171 bind(&okay); | 181 bind(&okay); |
| 172 | 182 |
| 173 if (offset == 0) { | 183 if (offset == 0) { |
| 174 // index must be int32. | 184 // index must be int32. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 195 if (offset != 0) { | 205 if (offset != 0) { |
| 196 lea(dst, Operand(object, offset)); | 206 lea(dst, Operand(object, offset)); |
| 197 } else { | 207 } else { |
| 198 // array access: calculate the destination address in the same manner as | 208 // array access: calculate the destination address in the same manner as |
| 199 // KeyedStoreIC::GenerateGeneric. | 209 // KeyedStoreIC::GenerateGeneric. |
| 200 lea(dst, FieldOperand(object, | 210 lea(dst, FieldOperand(object, |
| 201 index, | 211 index, |
| 202 times_pointer_size, | 212 times_pointer_size, |
| 203 FixedArray::kHeaderSize)); | 213 FixedArray::kHeaderSize)); |
| 204 } | 214 } |
| 205 RecordWriteHelper(object, dst, scratch); | 215 RecordWriteHelper(object, dst, scratch, save_fp); |
| 206 | 216 |
| 207 bind(&done); | 217 bind(&done); |
| 208 | 218 |
| 209 // Clobber all input registers when running with the debug-code flag | 219 // Clobber all input registers when running with the debug-code flag |
| 210 // turned on to provoke errors. | 220 // turned on to provoke errors. |
| 211 if (FLAG_debug_code) { | 221 if (FLAG_debug_code) { |
| 212 movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 222 movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 213 movq(scratch, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 223 movq(scratch, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 214 movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE); | 224 movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
| 215 } | 225 } |
| 216 } | 226 } |
| 217 #endif | 227 |
| 218 | 228 |
| 219 void MacroAssembler::Assert(Condition cc, const char* msg) { | 229 void MacroAssembler::Assert(Condition cc, const char* msg) { |
| 220 if (FLAG_debug_code) Check(cc, msg); | 230 if (FLAG_debug_code) Check(cc, msg); |
| 221 } | 231 } |
| 222 | 232 |
| 223 | 233 |
| 224 void MacroAssembler::AssertFastElements(Register elements) { | 234 void MacroAssembler::AssertFastElements(Register elements) { |
| 225 if (FLAG_debug_code) { | 235 if (FLAG_debug_code) { |
| 226 NearLabel ok; | 236 NearLabel ok; |
| 227 CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), | 237 CompareRoot(FieldOperand(elements, HeapObject::kMapOffset), |
| (...skipping 2119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2347 CPU::FlushICache(address_, size_); | 2357 CPU::FlushICache(address_, size_); |
| 2348 | 2358 |
| 2349 // Check that the code was patched as expected. | 2359 // Check that the code was patched as expected. |
| 2350 ASSERT(masm_.pc_ == address_ + size_); | 2360 ASSERT(masm_.pc_ == address_ + size_); |
| 2351 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 2361 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
| 2352 } | 2362 } |
| 2353 | 2363 |
| 2354 } } // namespace v8::internal | 2364 } } // namespace v8::internal |
| 2355 | 2365 |
| 2356 #endif // V8_TARGET_ARCH_X64 | 2366 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |