| 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 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 | 91 |
| 92 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); | 92 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); |
| 93 GenerateTailCallToReturnedCode(masm); | 93 GenerateTailCallToReturnedCode(masm); |
| 94 | 94 |
| 95 __ bind(&ok); | 95 __ bind(&ok); |
| 96 GenerateTailCallToSharedCode(masm); | 96 GenerateTailCallToSharedCode(masm); |
| 97 } | 97 } |
| 98 | 98 |
| 99 | 99 |
| 100 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 100 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
| 101 bool is_api_function, | 101 bool is_api_function) { |
| 102 bool create_memento) { | |
| 103 // ----------- S t a t e ------------- | 102 // ----------- S t a t e ------------- |
| 104 // -- rax: number of arguments | 103 // -- rax: number of arguments |
| 105 // -- rdi: constructor function | 104 // -- rdi: constructor function |
| 106 // -- rbx: allocation site or undefined | 105 // -- rbx: allocation site or undefined |
| 107 // -- rdx: original constructor | 106 // -- rdx: original constructor |
| 108 // ----------------------------------- | 107 // ----------------------------------- |
| 109 | 108 |
| 110 // Should never create mementos for api functions. | |
| 111 DCHECK(!is_api_function || !create_memento); | |
| 112 | |
| 113 // Enter a construct frame. | 109 // Enter a construct frame. |
| 114 { | 110 { |
| 115 FrameScope scope(masm, StackFrame::CONSTRUCT); | 111 FrameScope scope(masm, StackFrame::CONSTRUCT); |
| 116 | 112 |
| 117 // Preserve the incoming parameters on the stack. | 113 // Preserve the incoming parameters on the stack. |
| 118 __ AssertUndefinedOrAllocationSite(rbx); | 114 __ AssertUndefinedOrAllocationSite(rbx); |
| 119 __ Push(rbx); | 115 __ Push(rbx); |
| 120 __ Integer32ToSmi(rax, rax); | 116 __ Integer32ToSmi(rax, rax); |
| 121 __ Push(rax); | 117 __ Push(rax); |
| 122 __ Push(rdi); | 118 __ Push(rdi); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 __ Pop(rdx); | 178 __ Pop(rdx); |
| 183 __ Pop(rax); | 179 __ Pop(rax); |
| 184 __ movl(rsi, Immediate(Map::kSlackTrackingCounterEnd - 1)); | 180 __ movl(rsi, Immediate(Map::kSlackTrackingCounterEnd - 1)); |
| 185 | 181 |
| 186 __ bind(&allocate); | 182 __ bind(&allocate); |
| 187 } | 183 } |
| 188 | 184 |
| 189 // Now allocate the JSObject on the heap. | 185 // Now allocate the JSObject on the heap. |
| 190 __ movzxbp(rdi, FieldOperand(rax, Map::kInstanceSizeOffset)); | 186 __ movzxbp(rdi, FieldOperand(rax, Map::kInstanceSizeOffset)); |
| 191 __ shlp(rdi, Immediate(kPointerSizeLog2)); | 187 __ shlp(rdi, Immediate(kPointerSizeLog2)); |
| 192 if (create_memento) { | |
| 193 __ addp(rdi, Immediate(AllocationMemento::kSize)); | |
| 194 } | |
| 195 // rdi: size of new object | 188 // rdi: size of new object |
| 196 __ Allocate(rdi, | 189 __ Allocate(rdi, |
| 197 rbx, | 190 rbx, |
| 198 rdi, | 191 rdi, |
| 199 no_reg, | 192 no_reg, |
| 200 &rt_call, | 193 &rt_call, |
| 201 NO_ALLOCATION_FLAGS); | 194 NO_ALLOCATION_FLAGS); |
| 202 Factory* factory = masm->isolate()->factory(); | |
| 203 // Allocated the JSObject, now initialize the fields. | 195 // Allocated the JSObject, now initialize the fields. |
| 204 // rax: initial map | 196 // rax: initial map |
| 205 // rbx: JSObject (not HeapObject tagged - the actual address). | 197 // rbx: JSObject (not HeapObject tagged - the actual address). |
| 206 // rdi: start of next object (including memento if create_memento) | 198 // rdi: start of next object |
| 207 __ movp(Operand(rbx, JSObject::kMapOffset), rax); | 199 __ movp(Operand(rbx, JSObject::kMapOffset), rax); |
| 208 __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex); | 200 __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex); |
| 209 __ movp(Operand(rbx, JSObject::kPropertiesOffset), rcx); | 201 __ movp(Operand(rbx, JSObject::kPropertiesOffset), rcx); |
| 210 __ movp(Operand(rbx, JSObject::kElementsOffset), rcx); | 202 __ movp(Operand(rbx, JSObject::kElementsOffset), rcx); |
| 211 // Set extra fields in the newly allocated object. | 203 // Set extra fields in the newly allocated object. |
| 212 // rax: initial map | 204 // rax: initial map |
| 213 // rbx: JSObject | 205 // rbx: JSObject |
| 214 // rdi: start of next object (including memento if create_memento) | 206 // rdi: start of next object |
| 215 // rsi: slack tracking counter (non-API function case) | 207 // rsi: slack tracking counter (non-API function case) |
| 216 __ leap(rcx, Operand(rbx, JSObject::kHeaderSize)); | 208 __ leap(rcx, Operand(rbx, JSObject::kHeaderSize)); |
| 217 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); | 209 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); |
| 218 if (!is_api_function) { | 210 if (!is_api_function) { |
| 219 Label no_inobject_slack_tracking; | 211 Label no_inobject_slack_tracking; |
| 220 | 212 |
| 221 // Check if slack tracking is enabled. | 213 // Check if slack tracking is enabled. |
| 222 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd)); | 214 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd)); |
| 223 __ j(less, &no_inobject_slack_tracking); | 215 __ j(less, &no_inobject_slack_tracking); |
| 224 | 216 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 236 __ cmpp(rsi, rdi); | 228 __ cmpp(rsi, rdi); |
| 237 __ Assert(less_equal, | 229 __ Assert(less_equal, |
| 238 kUnexpectedNumberOfPreAllocatedPropertyFields); | 230 kUnexpectedNumberOfPreAllocatedPropertyFields); |
| 239 } | 231 } |
| 240 __ InitializeFieldsWithFiller(rcx, rsi, rdx); | 232 __ InitializeFieldsWithFiller(rcx, rsi, rdx); |
| 241 __ LoadRoot(rdx, Heap::kOnePointerFillerMapRootIndex); | 233 __ LoadRoot(rdx, Heap::kOnePointerFillerMapRootIndex); |
| 242 // Fill the remaining fields with one pointer filler map. | 234 // Fill the remaining fields with one pointer filler map. |
| 243 | 235 |
| 244 __ bind(&no_inobject_slack_tracking); | 236 __ bind(&no_inobject_slack_tracking); |
| 245 } | 237 } |
| 246 if (create_memento) { | |
| 247 __ leap(rsi, Operand(rdi, -AllocationMemento::kSize)); | |
| 248 __ InitializeFieldsWithFiller(rcx, rsi, rdx); | |
| 249 | 238 |
| 250 // Fill in memento fields if necessary. | 239 __ InitializeFieldsWithFiller(rcx, rdi, rdx); |
| 251 // rsi: points to the allocated but uninitialized memento. | |
| 252 __ Move(Operand(rsi, AllocationMemento::kMapOffset), | |
| 253 factory->allocation_memento_map()); | |
| 254 // Get the cell or undefined. | |
| 255 __ movp(rdx, Operand(rsp, 3 * kPointerSize)); | |
| 256 __ AssertUndefinedOrAllocationSite(rdx); | |
| 257 __ movp(Operand(rsi, AllocationMemento::kAllocationSiteOffset), rdx); | |
| 258 } else { | |
| 259 __ InitializeFieldsWithFiller(rcx, rdi, rdx); | |
| 260 } | |
| 261 | 240 |
| 262 // Add the object tag to make the JSObject real, so that we can continue | 241 // Add the object tag to make the JSObject real, so that we can continue |
| 263 // and jump into the continuation code at any time from now on. | 242 // and jump into the continuation code at any time from now on. |
| 264 // rbx: JSObject (untagged) | 243 // rbx: JSObject (untagged) |
| 265 __ orp(rbx, Immediate(kHeapObjectTag)); | 244 __ orp(rbx, Immediate(kHeapObjectTag)); |
| 266 | 245 |
| 267 // Continue with JSObject being successfully allocated | 246 // Continue with JSObject being successfully allocated |
| 268 // rbx: JSObject (tagged) | 247 // rbx: JSObject (tagged) |
| 269 __ jmp(&allocated); | 248 __ jmp(&allocated); |
| 270 } | 249 } |
| 271 | 250 |
| 272 // Allocate the new receiver object using the runtime call. | 251 // Allocate the new receiver object using the runtime call. |
| 273 // rdx: original constructor | 252 // rdx: original constructor |
| 274 __ bind(&rt_call); | 253 __ bind(&rt_call); |
| 275 int offset = kPointerSize; | 254 int offset = kPointerSize; |
| 276 if (create_memento) { | |
| 277 // Get the cell or allocation site. | |
| 278 __ movp(rdi, Operand(rsp, kPointerSize * 3)); | |
| 279 __ Push(rdi); // argument 1: allocation site | |
| 280 offset += kPointerSize; | |
| 281 } | |
| 282 | 255 |
| 283 // Must restore rsi (context) and rdi (constructor) before calling runtime. | 256 // Must restore rsi (context) and rdi (constructor) before calling runtime. |
| 284 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 257 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 285 __ movp(rdi, Operand(rsp, offset)); | 258 __ movp(rdi, Operand(rsp, offset)); |
| 286 __ Push(rdi); // argument 2/1: constructor function | 259 __ Push(rdi); // argument 2/1: constructor function |
| 287 __ Push(rdx); // argument 3/2: original constructor | 260 __ Push(rdx); // argument 3/2: original constructor |
| 288 if (create_memento) { | 261 __ CallRuntime(Runtime::kNewObject, 2); |
| 289 __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3); | |
| 290 } else { | |
| 291 __ CallRuntime(Runtime::kNewObject, 2); | |
| 292 } | |
| 293 __ movp(rbx, rax); // store result in rbx | 262 __ movp(rbx, rax); // store result in rbx |
| 294 | 263 |
| 295 // Runtime_NewObjectWithAllocationSite increments allocation count. | |
| 296 // Skip the increment. | |
| 297 Label count_incremented; | |
| 298 if (create_memento) { | |
| 299 __ jmp(&count_incremented); | |
| 300 } | |
| 301 | |
| 302 // New object allocated. | 264 // New object allocated. |
| 303 // rbx: newly allocated object | 265 // rbx: newly allocated object |
| 304 __ bind(&allocated); | 266 __ bind(&allocated); |
| 305 | 267 |
| 306 if (create_memento) { | |
| 307 __ movp(rcx, Operand(rsp, 3 * kPointerSize)); | |
| 308 __ Cmp(rcx, masm->isolate()->factory()->undefined_value()); | |
| 309 __ j(equal, &count_incremented); | |
| 310 // rcx is an AllocationSite. We are creating a memento from it, so we | |
| 311 // need to increment the memento create count. | |
| 312 __ SmiAddConstant( | |
| 313 FieldOperand(rcx, AllocationSite::kPretenureCreateCountOffset), | |
| 314 Smi::FromInt(1)); | |
| 315 __ bind(&count_incremented); | |
| 316 } | |
| 317 | |
| 318 // Restore the parameters. | 268 // Restore the parameters. |
| 319 __ Pop(rdx); | 269 __ Pop(rdx); |
| 320 __ Pop(rdi); | 270 __ Pop(rdi); |
| 321 | 271 |
| 322 // Retrieve smi-tagged arguments count from the stack. | 272 // Retrieve smi-tagged arguments count from the stack. |
| 323 __ movp(rax, Operand(rsp, 0)); | 273 __ movp(rax, Operand(rsp, 0)); |
| 324 __ SmiToInteger32(rax, rax); | 274 __ SmiToInteger32(rax, rax); |
| 325 | 275 |
| 326 // Push new.target onto the construct frame. This is stored just below the | 276 // Push new.target onto the construct frame. This is stored just below the |
| 327 // receiver on the stack. | 277 // receiver on the stack. |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 396 SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2); | 346 SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2); |
| 397 __ leap(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize)); | 347 __ leap(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize)); |
| 398 __ PushReturnAddressFrom(rcx); | 348 __ PushReturnAddressFrom(rcx); |
| 399 Counters* counters = masm->isolate()->counters(); | 349 Counters* counters = masm->isolate()->counters(); |
| 400 __ IncrementCounter(counters->constructed_objects(), 1); | 350 __ IncrementCounter(counters->constructed_objects(), 1); |
| 401 __ ret(0); | 351 __ ret(0); |
| 402 } | 352 } |
| 403 | 353 |
| 404 | 354 |
| 405 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { | 355 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
| 406 Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new); | 356 Generate_JSConstructStubHelper(masm, false); |
| 407 } | 357 } |
| 408 | 358 |
| 409 | 359 |
| 410 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { | 360 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { |
| 411 Generate_JSConstructStubHelper(masm, true, false); | 361 Generate_JSConstructStubHelper(masm, true); |
| 412 } | 362 } |
| 413 | 363 |
| 414 | 364 |
| 415 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { | 365 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { |
| 416 // ----------- S t a t e ------------- | 366 // ----------- S t a t e ------------- |
| 417 // -- rax: number of arguments | 367 // -- rax: number of arguments |
| 418 // -- rdi: constructor function | 368 // -- rdi: constructor function |
| 419 // -- rbx: allocation site or undefined | 369 // -- rbx: allocation site or undefined |
| 420 // -- rdx: original constructor | 370 // -- rdx: original constructor |
| 421 // ----------------------------------- | 371 // ----------------------------------- |
| (...skipping 1459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1881 __ ret(0); | 1831 __ ret(0); |
| 1882 } | 1832 } |
| 1883 | 1833 |
| 1884 | 1834 |
| 1885 #undef __ | 1835 #undef __ |
| 1886 | 1836 |
| 1887 } // namespace internal | 1837 } // namespace internal |
| 1888 } // namespace v8 | 1838 } // namespace v8 |
| 1889 | 1839 |
| 1890 #endif // V8_TARGET_ARCH_X64 | 1840 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |