Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(210)

Side by Side Diff: src/x64/macro-assembler-x64.cc

Issue 1689010: X64: Faster push/pop implementation. (Closed)
Patch Set: Addressed review comments. Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/x64/macro-assembler-x64.h ('k') | src/x64/stub-cache-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 94
95 // Compute the bit addr in the remembered set/index of the pointer in the 95 // Compute the bit addr in the remembered set/index of the pointer in the
96 // page. Reuse 'addr' as pointer_offset. 96 // page. Reuse 'addr' as pointer_offset.
97 subq(addr, page_start); 97 subq(addr, page_start);
98 shr(addr, Immediate(kPointerSizeLog2)); 98 shr(addr, Immediate(kPointerSizeLog2));
99 Register pointer_offset = addr; 99 Register pointer_offset = addr;
100 100
101 // If the bit offset lies beyond the normal remembered set range, it is in 101 // If the bit offset lies beyond the normal remembered set range, it is in
102 // the extra remembered set area of a large object. 102 // the extra remembered set area of a large object.
103 cmpq(pointer_offset, Immediate(Page::kPageSize / kPointerSize)); 103 cmpq(pointer_offset, Immediate(Page::kPageSize / kPointerSize));
104 j(less, &fast); 104 j(below, &fast);
105
106 // We have a large object containing pointers. It must be a FixedArray.
105 107
106 // Adjust 'page_start' so that addressing using 'pointer_offset' hits the 108 // Adjust 'page_start' so that addressing using 'pointer_offset' hits the
107 // extra remembered set after the large object. 109 // extra remembered set after the large object.
108 110
109 // Load the array length into 'scratch'. 111 // Load the array length into 'scratch'.
110 movl(scratch, 112 movl(scratch,
111 Operand(page_start, 113 Operand(page_start,
112 Page::kObjectStartOffset + FixedArray::kLengthOffset)); 114 Page::kObjectStartOffset + FixedArray::kLengthOffset));
113 Register array_length = scratch; 115 Register array_length = scratch;
114 116
115 // Extra remembered set starts right after the large object (a FixedArray), at 117 // Extra remembered set starts right after the large object (a FixedArray), at
116 // page_start + kObjectStartOffset + objectSize 118 // page_start + kObjectStartOffset + objectSize
117 // where objectSize is FixedArray::kHeaderSize + kPointerSize * array_length. 119 // where objectSize is FixedArray::kHeaderSize + kPointerSize * array_length.
118 // Add the delta between the end of the normal RSet and the start of the 120 // Add the delta between the end of the normal RSet and the start of the
119 // extra RSet to 'page_start', so that addressing the bit using 121 // extra RSet to 'page_start', so that addressing the bit using
120 // 'pointer_offset' hits the extra RSet words. 122 // 'pointer_offset' hits the extra RSet words.
121 lea(page_start, 123 lea(page_start,
122 Operand(page_start, array_length, times_pointer_size, 124 Operand(page_start, array_length, times_pointer_size,
123 Page::kObjectStartOffset + FixedArray::kHeaderSize 125 Page::kObjectStartOffset + FixedArray::kHeaderSize
124 - Page::kRSetEndOffset)); 126 - Page::kRSetEndOffset));
125 127
126 // NOTE: For now, we use the bit-test-and-set (bts) x86 instruction 128 // NOTE: For now, we use the bit-test-and-set (bts) x86 instruction
127 // to limit code size. We should probably evaluate this decision by 129 // to limit code size. We should probably evaluate this decision by
128 // measuring the performance of an equivalent implementation using 130 // measuring the performance of an equivalent implementation using
129 // "simpler" instructions 131 // "simpler" instructions
130 bind(&fast); 132 bind(&fast);
131 bts(Operand(page_start, Page::kRSetOffset), pointer_offset); 133 bts(Operand(page_start, Page::kRSetOffset), pointer_offset);
132 } 134 }
133 135
134 136
135 void MacroAssembler::InNewSpace(Register object,
136 Register scratch,
137 Condition cc,
138 Label* branch) {
139 ASSERT(cc == equal || cc == not_equal);
140 if (!scratch.is(object)) {
141 movq(scratch, object);
142 }
143 ASSERT(is_int32(static_cast<int64_t>(Heap::NewSpaceMask())));
144 and_(scratch, Immediate(static_cast<int32_t>(Heap::NewSpaceMask())));
145 movq(kScratchRegister, ExternalReference::new_space_start());
146 cmpq(scratch, kScratchRegister);
147 j(cc, branch);
148 }
149
150
151 // Set the remembered set bit for [object+offset]. 137 // Set the remembered set bit for [object+offset].
152 // object is the object being stored into, value is the object being stored. 138 // object is the object being stored into, value is the object being stored.
153 // If offset is zero, then the smi_index register contains the array index into 139 // If offset is zero, then the smi_index register contains the array index into
154 // the elements array represented as a smi. Otherwise it can be used as a 140 // the elements array represented as a smi. Otherwise it can be used as a
155 // scratch register. 141 // scratch register.
156 // All registers are clobbered by the operation. 142 // All registers are clobbered by the operation.
157 void MacroAssembler::RecordWrite(Register object, 143 void MacroAssembler::RecordWrite(Register object,
158 int offset, 144 int offset,
159 Register value, 145 Register value,
160 Register smi_index) { 146 Register smi_index) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 // so either offset or offset + kHeapObjectTag must be a 192 // so either offset or offset + kHeapObjectTag must be a
207 // multiple of kPointerSize. 193 // multiple of kPointerSize.
208 ASSERT(IsAligned(offset, kPointerSize) || 194 ASSERT(IsAligned(offset, kPointerSize) ||
209 IsAligned(offset + kHeapObjectTag, kPointerSize)); 195 IsAligned(offset + kHeapObjectTag, kPointerSize));
210 196
211 // We use optimized write barrier code if the word being written to is not in 197 // We use optimized write barrier code if the word being written to is not in
212 // a large object page, or is in the first "page" of a large object page. 198 // a large object page, or is in the first "page" of a large object page.
213 // We make sure that an offset is inside the right limits whether it is 199 // We make sure that an offset is inside the right limits whether it is
214 // tagged or untagged. 200 // tagged or untagged.
215 if ((offset > 0) && (offset < Page::kMaxHeapObjectSize - kHeapObjectTag)) { 201 if ((offset > 0) && (offset < Page::kMaxHeapObjectSize - kHeapObjectTag)) {
216 // Compute the bit offset in the remembered set, leave it in 'value'. 202 // Compute the bit offset in the remembered set, leave it in 'scratch'.
217 lea(scratch, Operand(object, offset)); 203 lea(scratch, Operand(object, offset));
218 ASSERT(is_int32(Page::kPageAlignmentMask)); 204 ASSERT(is_int32(Page::kPageAlignmentMask));
219 and_(scratch, Immediate(static_cast<int32_t>(Page::kPageAlignmentMask))); 205 and_(scratch, Immediate(static_cast<int32_t>(Page::kPageAlignmentMask)));
220 shr(scratch, Immediate(kObjectAlignmentBits)); 206 shr(scratch, Immediate(kPointerSizeLog2));
221 207
222 // Compute the page address from the heap object pointer, leave it in 208 // Compute the page address from the heap object pointer, leave it in
223 // 'object' (immediate value is sign extended). 209 // 'object' (immediate value is sign extended).
224 and_(object, Immediate(~Page::kPageAlignmentMask)); 210 and_(object, Immediate(~Page::kPageAlignmentMask));
225 211
226 // NOTE: For now, we use the bit-test-and-set (bts) x86 instruction 212 // NOTE: For now, we use the bit-test-and-set (bts) x86 instruction
227 // to limit code size. We should probably evaluate this decision by 213 // to limit code size. We should probably evaluate this decision by
228 // measuring the performance of an equivalent implementation using 214 // measuring the performance of an equivalent implementation using
229 // "simpler" instructions 215 // "simpler" instructions
230 bts(Operand(object, Page::kRSetOffset), scratch); 216 bts(Operand(object, Page::kRSetOffset), scratch);
231 } else { 217 } else {
232 Register dst = smi_index; 218 Register dst = smi_index;
233 if (offset != 0) { 219 if (offset != 0) {
234 lea(dst, Operand(object, offset)); 220 lea(dst, Operand(object, offset));
235 } else { 221 } else {
236 // array access: calculate the destination address in the same manner as 222 // array access: calculate the destination address in the same manner as
237 // KeyedStoreIC::GenerateGeneric. 223 // KeyedStoreIC::GenerateGeneric.
238 SmiIndex index = SmiToIndex(smi_index, smi_index, kPointerSizeLog2); 224 SmiIndex index = SmiToIndex(smi_index, smi_index, kPointerSizeLog2);
239 lea(dst, Operand(object, 225 lea(dst, FieldOperand(object,
240 index.reg, 226 index.reg,
241 index.scale, 227 index.scale,
242 FixedArray::kHeaderSize - kHeapObjectTag)); 228 FixedArray::kHeaderSize));
243 } 229 }
244 // If we are already generating a shared stub, not inlining the 230 // If we are already generating a shared stub, not inlining the
245 // record write code isn't going to save us any memory. 231 // record write code isn't going to save us any memory.
246 if (generating_stub()) { 232 if (generating_stub()) {
247 RecordWriteHelper(object, dst, scratch); 233 RecordWriteHelper(object, dst, scratch);
248 } else { 234 } else {
249 RecordWriteStub stub(object, dst, scratch); 235 RecordWriteStub stub(object, dst, scratch);
250 CallStub(&stub); 236 CallStub(&stub);
251 } 237 }
252 } 238 }
253 239
254 bind(&done); 240 bind(&done);
255 241
256 // Clobber all input registers when running with the debug-code flag 242 // Clobber all input registers when running with the debug-code flag
257 // turned on to provoke errors. 243 // turned on to provoke errors.
258 if (FLAG_debug_code) { 244 if (FLAG_debug_code) {
259 movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE); 245 movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
260 movq(scratch, BitCast<int64_t>(kZapValue), RelocInfo::NONE); 246 movq(scratch, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
261 movq(smi_index, BitCast<int64_t>(kZapValue), RelocInfo::NONE); 247 movq(smi_index, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
262 } 248 }
263 } 249 }
264 250
265 251
252 void MacroAssembler::InNewSpace(Register object,
253 Register scratch,
254 Condition cc,
255 Label* branch) {
256 if (Serializer::enabled()) {
257 // Can't do arithmetic on external references if it might get serialized.
258 // The mask isn't really an address. We load it as an external reference in
259 // case the size of the new space is different between the snapshot maker
260 // and the running system.
261 if (scratch.is(object)) {
262 movq(kScratchRegister, ExternalReference::new_space_mask());
263 and_(scratch, kScratchRegister);
264 } else {
265 movq(scratch, ExternalReference::new_space_mask());
266 and_(scratch, object);
267 }
268 movq(kScratchRegister, ExternalReference::new_space_start());
269 cmpq(scratch, kScratchRegister);
270 j(cc, branch);
271 } else {
272 ASSERT(is_int32(static_cast<int64_t>(Heap::NewSpaceMask())));
273 intptr_t new_space_start =
274 reinterpret_cast<intptr_t>(Heap::NewSpaceStart());
275 movq(kScratchRegister, -new_space_start, RelocInfo::NONE);
276 if (scratch.is(object)) {
277 addq(scratch, kScratchRegister);
278 } else {
279 lea(scratch, Operand(object, kScratchRegister, times_1, 0));
280 }
281 and_(scratch, Immediate(static_cast<int32_t>(Heap::NewSpaceMask())));
282 j(cc, branch);
283 }
284 }
285
286
266 void MacroAssembler::Assert(Condition cc, const char* msg) { 287 void MacroAssembler::Assert(Condition cc, const char* msg) {
267 if (FLAG_debug_code) Check(cc, msg); 288 if (FLAG_debug_code) Check(cc, msg);
268 } 289 }
269 290
270 291
271 void MacroAssembler::Check(Condition cc, const char* msg) { 292 void MacroAssembler::Check(Condition cc, const char* msg) {
272 Label L; 293 Label L;
273 j(cc, &L); 294 j(cc, &L);
274 Abort(msg); 295 Abort(msg);
275 // will not return here 296 // will not return here
(...skipping 1878 matching lines...) Expand 10 before | Expand all | Expand 10 after
2154 // registers. 2175 // registers.
2155 ASSERT(!scratch.is(object_reg) && !scratch.is(holder_reg)); 2176 ASSERT(!scratch.is(object_reg) && !scratch.is(holder_reg));
2156 2177
2157 // Keep track of the current object in register reg. On the first 2178 // Keep track of the current object in register reg. On the first
2158 // iteration, reg is an alias for object_reg, on later iterations, 2179 // iteration, reg is an alias for object_reg, on later iterations,
2159 // it is an alias for holder_reg. 2180 // it is an alias for holder_reg.
2160 Register reg = object_reg; 2181 Register reg = object_reg;
2161 int depth = 0; 2182 int depth = 0;
2162 2183
2163 if (save_at_depth == depth) { 2184 if (save_at_depth == depth) {
2164 movq(Operand(rsp, kPointerSize), reg); 2185 movq(Operand(rsp, kPointerSize), object_reg);
2165 } 2186 }
2166 2187
2167 // Check the maps in the prototype chain. 2188 // Check the maps in the prototype chain.
2168 // Traverse the prototype chain from the object and do map checks. 2189 // Traverse the prototype chain from the object and do map checks.
2169 while (object != holder) { 2190 while (object != holder) {
2170 depth++; 2191 depth++;
2171 2192
2172 // Only global objects and objects that do not require access 2193 // Only global objects and objects that do not require access
2173 // checks are allowed in stubs. 2194 // checks are allowed in stubs.
2174 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 2195 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
(...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after
2680 CodePatcher::~CodePatcher() { 2701 CodePatcher::~CodePatcher() {
2681 // Indicate that code has changed. 2702 // Indicate that code has changed.
2682 CPU::FlushICache(address_, size_); 2703 CPU::FlushICache(address_, size_);
2683 2704
2684 // Check that the code was patched as expected. 2705 // Check that the code was patched as expected.
2685 ASSERT(masm_.pc_ == address_ + size_); 2706 ASSERT(masm_.pc_ == address_ + size_);
2686 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); 2707 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
2687 } 2708 }
2688 2709
2689 } } // namespace v8::internal 2710 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/x64/macro-assembler-x64.h ('k') | src/x64/stub-cache-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698