OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_X64 | 5 #if V8_TARGET_ARCH_X64 |
6 | 6 |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/codegen.h" | 8 #include "src/codegen.h" |
9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
10 #include "src/full-codegen/full-codegen.h" | 10 #include "src/full-codegen/full-codegen.h" |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 // rdi: constructor | 164 // rdi: constructor |
165 // rax: initial map (if proven valid below) | 165 // rax: initial map (if proven valid below) |
166 __ CmpObjectType(rax, MAP_TYPE, rbx); | 166 __ CmpObjectType(rax, MAP_TYPE, rbx); |
167 __ j(not_equal, &rt_call); | 167 __ j(not_equal, &rt_call); |
168 | 168 |
169 // Fall back to runtime if the expected base constructor and base | 169 // Fall back to runtime if the expected base constructor and base |
170 // constructor differ. | 170 // constructor differ. |
171 __ cmpp(rdi, FieldOperand(rax, Map::kConstructorOrBackPointerOffset)); | 171 __ cmpp(rdi, FieldOperand(rax, Map::kConstructorOrBackPointerOffset)); |
172 __ j(not_equal, &rt_call); | 172 __ j(not_equal, &rt_call); |
173 | 173 |
174 if (!is_api_function) { | |
175 Label allocate; | |
176 // The code below relies on these assumptions. | |
177 STATIC_ASSERT(Map::Counter::kShift + Map::Counter::kSize == 32); | |
178 // Check if slack tracking is enabled. | |
179 __ movl(rsi, FieldOperand(rax, Map::kBitField3Offset)); | |
180 __ shrl(rsi, Immediate(Map::Counter::kShift)); | |
181 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd)); | |
182 __ j(less, &allocate); | |
183 // Decrease generous allocation count. | |
184 __ subl(FieldOperand(rax, Map::kBitField3Offset), | |
185 Immediate(1 << Map::Counter::kShift)); | |
186 | |
187 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd)); | |
188 __ j(not_equal, &allocate); | |
189 | |
190 // Push the constructor, new_target and map to the stack, and | |
191 // the map again as an argument to the runtime call. | |
192 __ Push(rax); | |
193 __ Push(rdx); | |
194 __ Push(rdi); | |
195 | |
196 __ Push(rax); // initial map | |
197 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); | |
198 | |
199 __ Pop(rdi); | |
200 __ Pop(rdx); | |
201 __ Pop(rax); | |
202 __ movl(rsi, Immediate(Map::kSlackTrackingCounterEnd - 1)); | |
203 | |
204 __ bind(&allocate); | |
205 } | |
206 | |
207 // Now allocate the JSObject on the heap. | 174 // Now allocate the JSObject on the heap. |
208 __ movzxbp(r9, FieldOperand(rax, Map::kInstanceSizeOffset)); | 175 __ movzxbp(r9, FieldOperand(rax, Map::kInstanceSizeOffset)); |
209 __ shlp(r9, Immediate(kPointerSizeLog2)); | 176 __ shlp(r9, Immediate(kPointerSizeLog2)); |
210 // r9: size of new object | 177 // r9: size of new object |
211 __ Allocate(r9, rbx, r9, no_reg, &rt_call, NO_ALLOCATION_FLAGS); | 178 __ Allocate(r9, rbx, r9, no_reg, &rt_call, NO_ALLOCATION_FLAGS); |
212 // Allocated the JSObject, now initialize the fields. | 179 // Allocated the JSObject, now initialize the fields. |
213 // rdi: constructor | 180 // rdi: constructor |
214 // rdx: new target | 181 // rdx: new target |
215 // rax: initial map | 182 // rax: initial map |
216 // rbx: JSObject (not HeapObject tagged - the actual address). | 183 // rbx: JSObject (not HeapObject tagged - the actual address). |
217 // r9: start of next object | 184 // r9: start of next object |
218 __ movp(Operand(rbx, JSObject::kMapOffset), rax); | 185 __ movp(Operand(rbx, JSObject::kMapOffset), rax); |
219 __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex); | 186 __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex); |
220 __ movp(Operand(rbx, JSObject::kPropertiesOffset), rcx); | 187 __ movp(Operand(rbx, JSObject::kPropertiesOffset), rcx); |
221 __ movp(Operand(rbx, JSObject::kElementsOffset), rcx); | 188 __ movp(Operand(rbx, JSObject::kElementsOffset), rcx); |
222 // Set extra fields in the newly allocated object. | |
223 // rax: initial map | |
224 // rdx: new target | |
225 // rbx: JSObject | |
226 // r9: start of next object | |
227 // rsi: slack tracking counter (non-API function case) | |
228 __ leap(rcx, Operand(rbx, JSObject::kHeaderSize)); | 189 __ leap(rcx, Operand(rbx, JSObject::kHeaderSize)); |
| 190 |
| 191 // Add the object tag to make the JSObject real, so that we can continue |
| 192 // and jump into the continuation code at any time from now on. |
| 193 __ orp(rbx, Immediate(kHeapObjectTag)); |
| 194 |
| 195 // Fill all the in-object properties with the appropriate filler. |
| 196 // rbx: JSObject (tagged) |
| 197 // rcx: First in-object property of JSObject (not tagged) |
229 __ LoadRoot(r11, Heap::kUndefinedValueRootIndex); | 198 __ LoadRoot(r11, Heap::kUndefinedValueRootIndex); |
| 199 |
230 if (!is_api_function) { | 200 if (!is_api_function) { |
231 Label no_inobject_slack_tracking; | 201 Label no_inobject_slack_tracking; |
232 | 202 |
| 203 // The code below relies on these assumptions. |
| 204 STATIC_ASSERT(Map::Counter::kShift + Map::Counter::kSize == 32); |
233 // Check if slack tracking is enabled. | 205 // Check if slack tracking is enabled. |
| 206 __ movl(rsi, FieldOperand(rax, Map::kBitField3Offset)); |
| 207 __ shrl(rsi, Immediate(Map::Counter::kShift)); |
234 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd)); | 208 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd)); |
235 __ j(less, &no_inobject_slack_tracking); | 209 __ j(less, &no_inobject_slack_tracking); |
| 210 __ Push(rsi); // Save allocation count value. |
| 211 // Decrease generous allocation count. |
| 212 __ subl(FieldOperand(rax, Map::kBitField3Offset), |
| 213 Immediate(1 << Map::Counter::kShift)); |
236 | 214 |
237 // Allocate object with a slack. | 215 // Allocate object with a slack. |
238 __ movzxbp(rsi, FieldOperand(rax, Map::kUnusedPropertyFieldsOffset)); | 216 __ movzxbp(rsi, FieldOperand(rax, Map::kUnusedPropertyFieldsOffset)); |
239 __ negp(rsi); | 217 __ negp(rsi); |
240 __ leap(rsi, Operand(r9, rsi, times_pointer_size, 0)); | 218 __ leap(rsi, Operand(r9, rsi, times_pointer_size, 0)); |
241 // rsi: offset of first field after pre-allocated fields | 219 // rsi: offset of first field after pre-allocated fields |
242 if (FLAG_debug_code) { | 220 if (FLAG_debug_code) { |
243 __ cmpp(rcx, rsi); | 221 __ cmpp(rcx, rsi); |
244 __ Assert(less_equal, | 222 __ Assert(less_equal, |
245 kUnexpectedNumberOfPreAllocatedPropertyFields); | 223 kUnexpectedNumberOfPreAllocatedPropertyFields); |
246 } | 224 } |
247 __ InitializeFieldsWithFiller(rcx, rsi, r11); | 225 __ InitializeFieldsWithFiller(rcx, rsi, r11); |
248 | 226 |
249 // To allow truncation fill the remaining fields with one pointer | 227 // To allow truncation fill the remaining fields with one pointer |
250 // filler map. | 228 // filler map. |
251 __ LoadRoot(r11, Heap::kOnePointerFillerMapRootIndex); | 229 __ LoadRoot(r11, Heap::kOnePointerFillerMapRootIndex); |
| 230 __ InitializeFieldsWithFiller(rcx, r9, r11); |
| 231 |
| 232 __ Pop(rsi); // Restore allocation count value before decreasing. |
| 233 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd)); |
| 234 __ j(not_equal, &allocated); |
| 235 |
| 236 // Push the constructor, new_target and the object to the stack, |
| 237 // and then the initial map as an argument to the runtime call. |
| 238 __ Push(rdi); |
| 239 __ Push(rdx); |
| 240 __ Push(rbx); |
| 241 |
| 242 __ Push(rax); // initial map |
| 243 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); |
| 244 |
| 245 __ Pop(rbx); |
| 246 __ Pop(rdx); |
| 247 __ Pop(rdi); |
| 248 |
| 249 // Continue with JSObject being successfully allocated. |
| 250 // rdi: constructor |
| 251 // rdx: new target |
| 252 // rbx: JSObject (tagged) |
| 253 __ jmp(&allocated); |
252 | 254 |
253 __ bind(&no_inobject_slack_tracking); | 255 __ bind(&no_inobject_slack_tracking); |
254 } | 256 } |
255 | 257 |
256 __ InitializeFieldsWithFiller(rcx, r9, r11); | 258 __ InitializeFieldsWithFiller(rcx, r9, r11); |
257 | 259 |
258 // Add the object tag to make the JSObject real, so that we can continue | |
259 // and jump into the continuation code at any time from now on. | |
260 // rbx: JSObject (untagged) | |
261 __ orp(rbx, Immediate(kHeapObjectTag)); | |
262 | |
263 // Continue with JSObject being successfully allocated | 260 // Continue with JSObject being successfully allocated |
264 // rdi: constructor | 261 // rdi: constructor |
265 // rdx: new target | 262 // rdx: new target |
266 // rbx: JSObject (tagged) | 263 // rbx: JSObject (tagged) |
267 __ jmp(&allocated); | 264 __ jmp(&allocated); |
268 } | 265 } |
269 | 266 |
270 // Allocate the new receiver object using the runtime call. | 267 // Allocate the new receiver object using the runtime call. |
271 // rdi: constructor | 268 // rdi: constructor |
272 // rdx: new target | 269 // rdx: new target |
(...skipping 1788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2061 __ ret(0); | 2058 __ ret(0); |
2062 } | 2059 } |
2063 | 2060 |
2064 | 2061 |
2065 #undef __ | 2062 #undef __ |
2066 | 2063 |
2067 } // namespace internal | 2064 } // namespace internal |
2068 } // namespace v8 | 2065 } // namespace v8 |
2069 | 2066 |
2070 #endif // V8_TARGET_ARCH_X64 | 2067 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |