| 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 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
| 8 | 8 |
| 9 #include "src/code-factory.h" | 9 #include "src/code-factory.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 if (create_memento) { | 129 if (create_memento) { |
| 130 __ jmp(count_incremented); | 130 __ jmp(count_incremented); |
| 131 } else { | 131 } else { |
| 132 __ jmp(allocated); | 132 __ jmp(allocated); |
| 133 } | 133 } |
| 134 } | 134 } |
| 135 | 135 |
| 136 | 136 |
| 137 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 137 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
| 138 bool is_api_function, | 138 bool is_api_function, |
| 139 bool use_new_target, |
| 139 bool create_memento) { | 140 bool create_memento) { |
| 140 // ----------- S t a t e ------------- | 141 // ----------- S t a t e ------------- |
| 141 // -- rax: number of arguments | 142 // -- rax: number of arguments |
| 142 // -- rdi: constructor function | 143 // -- rdi: constructor function |
| 143 // -- rbx: allocation site or undefined | 144 // -- rbx: allocation site or undefined |
| 144 // -- rdx: original constructor | 145 // -- rdx: original constructor |
| 145 // ----------------------------------- | 146 // ----------------------------------- |
| 146 | 147 |
| 147 // Should never create mementos for api functions. | 148 // Should never create mementos for api functions. |
| 148 DCHECK(!is_api_function || !create_memento); | 149 DCHECK(!is_api_function || !create_memento); |
| 149 | 150 |
| 150 // Enter a construct frame. | 151 // Enter a construct frame. |
| 151 { | 152 { |
| 152 FrameScope scope(masm, StackFrame::CONSTRUCT); | 153 FrameScope scope(masm, StackFrame::CONSTRUCT); |
| 153 | 154 |
| 154 if (create_memento) { | 155 if (create_memento) { |
| 155 __ AssertUndefinedOrAllocationSite(rbx); | 156 __ AssertUndefinedOrAllocationSite(rbx); |
| 156 __ Push(rbx); | 157 __ Push(rbx); |
| 157 } | 158 } |
| 158 | 159 |
| 159 // Store a smi-tagged arguments count on the stack. | 160 // Store a smi-tagged arguments count on the stack. |
| 160 __ Integer32ToSmi(rax, rax); | 161 __ Integer32ToSmi(rax, rax); |
| 161 __ Push(rax); | 162 __ Push(rax); |
| 162 | 163 |
| 163 // Push the function to invoke on the stack. | 164 // Push the function to invoke on the stack. |
| 165 |
| 166 if (use_new_target) { |
| 167 __ Push(rdx); |
| 168 } |
| 164 __ Push(rdi); | 169 __ Push(rdi); |
| 165 | 170 |
| 166 Label rt_call, normal_new, allocated, count_incremented; | 171 Label rt_call, normal_new, allocated, count_incremented; |
| 167 __ cmpp(rdx, rdi); | 172 __ cmpp(rdx, rdi); |
| 168 __ j(equal, &normal_new); | 173 __ j(equal, &normal_new); |
| 169 | 174 |
| 170 Generate_Runtime_NewObject(masm, create_memento, rdx, &count_incremented, | 175 Generate_Runtime_NewObject(masm, create_memento, rdx, &count_incremented, |
| 171 &allocated); | 176 &allocated); |
| 172 | 177 |
| 173 __ bind(&normal_new); | 178 __ bind(&normal_new); |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 // rcx is an AllocationSite. We are creating a memento from it, so we | 407 // rcx is an AllocationSite. We are creating a memento from it, so we |
| 403 // need to increment the memento create count. | 408 // need to increment the memento create count. |
| 404 __ SmiAddConstant( | 409 __ SmiAddConstant( |
| 405 FieldOperand(rcx, AllocationSite::kPretenureCreateCountOffset), | 410 FieldOperand(rcx, AllocationSite::kPretenureCreateCountOffset), |
| 406 Smi::FromInt(1)); | 411 Smi::FromInt(1)); |
| 407 __ bind(&count_incremented); | 412 __ bind(&count_incremented); |
| 408 } | 413 } |
| 409 | 414 |
| 410 // Retrieve the function from the stack. | 415 // Retrieve the function from the stack. |
| 411 __ Pop(rdi); | 416 __ Pop(rdi); |
| 417 if (use_new_target) { |
| 418 __ Pop(rdx); |
| 419 } |
| 412 | 420 |
| 413 // Retrieve smi-tagged arguments count from the stack. | 421 // Retrieve smi-tagged arguments count from the stack. |
| 414 __ movp(rax, Operand(rsp, 0)); | 422 __ movp(rax, Operand(rsp, 0)); |
| 415 __ SmiToInteger32(rax, rax); | 423 __ SmiToInteger32(rax, rax); |
| 416 | 424 |
| 417 // Push the allocated receiver to the stack. We need two copies | 425 // Push the allocated receiver to the stack. We need two copies |
| 418 // because we may have to return the original one and the calling | 426 // because we may have to return the original one and the calling |
| 419 // conventions dictate that the called function pops the receiver. | 427 // conventions dictate that the called function pops the receiver. |
| 420 __ Push(rbx); | 428 __ Push(rbx); |
| 429 if (use_new_target) { |
| 430 __ Push(rdx); |
| 431 } |
| 421 __ Push(rbx); | 432 __ Push(rbx); |
| 422 | 433 |
| 423 // Set up pointer to last argument. | 434 // Set up pointer to last argument. |
| 424 __ leap(rbx, Operand(rbp, StandardFrameConstants::kCallerSPOffset)); | 435 __ leap(rbx, Operand(rbp, StandardFrameConstants::kCallerSPOffset)); |
| 425 | 436 |
| 426 // Copy arguments and receiver to the expression stack. | 437 // Copy arguments and receiver to the expression stack. |
| 427 Label loop, entry; | 438 Label loop, entry; |
| 428 __ movp(rcx, rax); | 439 __ movp(rcx, rax); |
| 429 __ jmp(&entry); | 440 __ jmp(&entry); |
| 430 __ bind(&loop); | 441 __ bind(&loop); |
| 431 __ Push(Operand(rbx, rcx, times_pointer_size, 0)); | 442 __ Push(Operand(rbx, rcx, times_pointer_size, 0)); |
| 432 __ bind(&entry); | 443 __ bind(&entry); |
| 433 __ decp(rcx); | 444 __ decp(rcx); |
| 434 __ j(greater_equal, &loop); | 445 __ j(greater_equal, &loop); |
| 435 | 446 |
| 447 // if (use_new_target) { |
| 448 // __ incp(rax); // Pushed new.target |
| 449 // } |
| 450 |
| 436 // Call the function. | 451 // Call the function. |
| 437 if (is_api_function) { | 452 if (is_api_function) { |
| 438 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 453 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 439 Handle<Code> code = | 454 Handle<Code> code = |
| 440 masm->isolate()->builtins()->HandleApiCallConstruct(); | 455 masm->isolate()->builtins()->HandleApiCallConstruct(); |
| 441 __ Call(code, RelocInfo::CODE_TARGET); | 456 __ Call(code, RelocInfo::CODE_TARGET); |
| 442 } else { | 457 } else { |
| 443 ParameterCount actual(rax); | 458 ParameterCount actual(rax); |
| 444 __ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper()); | 459 __ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper()); |
| 445 } | 460 } |
| 446 | 461 |
| 447 // Store offset of return address for deoptimizer. | 462 // Store offset of return address for deoptimizer. |
| 448 if (!is_api_function) { | 463 if (!is_api_function && !use_new_target) { |
| 449 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); | 464 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); |
| 450 } | 465 } |
| 451 | 466 |
| 452 // Restore context from the frame. | 467 // Restore context from the frame. |
| 453 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 468 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 454 | 469 |
| 455 // If the result is an object (in the ECMA sense), we should get rid | 470 // If the result is an object (in the ECMA sense), we should get rid |
| 456 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 | 471 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 |
| 457 // on page 74. | 472 // on page 74. |
| 458 Label use_receiver, exit; | 473 Label use_receiver, exit; |
| 459 // If the result is a smi, it is *not* an object in the ECMA sense. | 474 // If the result is a smi, it is *not* an object in the ECMA sense. |
| 460 __ JumpIfSmi(rax, &use_receiver); | 475 __ JumpIfSmi(rax, &use_receiver); |
| 461 | 476 |
| 462 // If the type of the result (stored in its map) is less than | 477 // If the type of the result (stored in its map) is less than |
| 463 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. | 478 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. |
| 464 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); | 479 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); |
| 465 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); | 480 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); |
| 466 __ j(above_equal, &exit); | 481 __ j(above_equal, &exit); |
| 467 | 482 |
| 468 // Throw away the result of the constructor invocation and use the | 483 // Throw away the result of the constructor invocation and use the |
| 469 // on-stack receiver as the result. | 484 // on-stack receiver as the result. |
| 470 __ bind(&use_receiver); | 485 __ bind(&use_receiver); |
| 471 __ movp(rax, Operand(rsp, 0)); | 486 __ movp(rax, Operand(rsp, (use_new_target ? 1 : 0) * kPointerSize)); |
| 472 | 487 |
| 473 // Restore the arguments count and leave the construct frame. | 488 // Restore the arguments count and leave the construct frame. |
| 474 __ bind(&exit); | 489 __ bind(&exit); |
| 475 __ movp(rbx, Operand(rsp, kPointerSize)); // Get arguments count. | 490 // Get arguments count. |
| 491 int offset = (use_new_target ? 2 : 1) * kPointerSize; |
| 492 __ movp(rbx, Operand(rsp, offset)); |
| 476 | 493 |
| 477 // Leave construct frame. | 494 // Leave construct frame. |
| 478 } | 495 } |
| 479 | 496 |
| 480 // Remove caller arguments from the stack and return. | 497 // Remove caller arguments from the stack and return. |
| 481 __ PopReturnAddressTo(rcx); | 498 __ PopReturnAddressTo(rcx); |
| 482 SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2); | 499 SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2); |
| 483 __ leap(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize)); | 500 __ leap(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize)); |
| 484 __ PushReturnAddressFrom(rcx); | 501 __ PushReturnAddressFrom(rcx); |
| 485 Counters* counters = masm->isolate()->counters(); | 502 Counters* counters = masm->isolate()->counters(); |
| 486 __ IncrementCounter(counters->constructed_objects(), 1); | 503 __ IncrementCounter(counters->constructed_objects(), 1); |
| 487 __ ret(0); | 504 __ ret(0); |
| 488 } | 505 } |
| 489 | 506 |
| 490 | 507 |
| 491 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { | 508 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
| 492 Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new); | 509 Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new); |
| 493 } | 510 } |
| 494 | 511 |
| 495 | 512 |
| 496 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { | 513 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { |
| 497 Generate_JSConstructStubHelper(masm, true, false); | 514 Generate_JSConstructStubHelper(masm, true, false, false); |
| 498 } | 515 } |
| 499 | 516 |
| 500 | 517 |
| 518 void Builtins::Generate_JSConstructStubNewTarget(MacroAssembler* masm) { |
| 519 Generate_JSConstructStubHelper(masm, false, true, FLAG_pretenuring_call_new); |
| 520 } |
| 521 |
| 522 |
| 501 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { | 523 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { |
| 502 // ----------- S t a t e ------------- | 524 // ----------- S t a t e ------------- |
| 503 // -- rax: number of arguments | 525 // -- rax: number of arguments |
| 504 // -- rdi: constructor function | 526 // -- rdi: constructor function |
| 505 // -- rbx: allocation site or undefined | 527 // -- rbx: allocation site or undefined |
| 506 // -- rdx: original constructor | 528 // -- rdx: original constructor |
| 507 // ----------------------------------- | 529 // ----------------------------------- |
| 508 // TODO(dslomov): support pretenuring | 530 // TODO(dslomov): support pretenuring |
| 509 CHECK(!FLAG_pretenuring_call_new); | 531 CHECK(!FLAG_pretenuring_call_new); |
| 510 | 532 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 528 // Copy arguments and receiver to the expression stack. | 550 // Copy arguments and receiver to the expression stack. |
| 529 Label loop, entry; | 551 Label loop, entry; |
| 530 __ movp(rcx, rax); | 552 __ movp(rcx, rax); |
| 531 __ jmp(&entry); | 553 __ jmp(&entry); |
| 532 __ bind(&loop); | 554 __ bind(&loop); |
| 533 __ Push(Operand(rbx, rcx, times_pointer_size, 0)); | 555 __ Push(Operand(rbx, rcx, times_pointer_size, 0)); |
| 534 __ bind(&entry); | 556 __ bind(&entry); |
| 535 __ decp(rcx); | 557 __ decp(rcx); |
| 536 __ j(greater_equal, &loop); | 558 __ j(greater_equal, &loop); |
| 537 | 559 |
| 538 __ incp(rax); // Pushed new.target. | 560 // __ incp(rax); // Pushed new.target. |
| 539 | 561 |
| 540 // Handle step in. | 562 // Handle step in. |
| 541 Label skip_step_in; | 563 Label skip_step_in; |
| 542 ExternalReference debug_step_in_fp = | 564 ExternalReference debug_step_in_fp = |
| 543 ExternalReference::debug_step_in_fp_address(masm->isolate()); | 565 ExternalReference::debug_step_in_fp_address(masm->isolate()); |
| 544 __ Move(kScratchRegister, debug_step_in_fp); | 566 __ Move(kScratchRegister, debug_step_in_fp); |
| 545 __ cmpp(Operand(kScratchRegister, 0), Immediate(0)); | 567 __ cmpp(Operand(kScratchRegister, 0), Immediate(0)); |
| 546 __ j(equal, &skip_step_in); | 568 __ j(equal, &skip_step_in); |
| 547 | 569 |
| 548 __ Push(rax); | 570 __ Push(rax); |
| 549 __ Push(rdi); | 571 __ Push(rdi); |
| 550 __ Push(rdi); | 572 __ Push(rdi); |
| 551 __ CallRuntime(Runtime::kHandleStepInForDerivedConstructors, 1); | 573 __ CallRuntime(Runtime::kHandleStepInForDerivedConstructors, 1); |
| 552 __ Pop(rdi); | 574 __ Pop(rdi); |
| 553 __ Pop(rax); | 575 __ Pop(rax); |
| 554 | 576 |
| 555 __ bind(&skip_step_in); | 577 __ bind(&skip_step_in); |
| 556 | 578 |
| 557 // Call the function. | 579 // Call the function. |
| 558 ParameterCount actual(rax); | 580 ParameterCount actual(rax); |
| 559 __ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper()); | 581 __ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper()); |
| 560 | 582 |
| 561 // Restore context from the frame. | 583 // Restore context from the frame. |
| 562 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 584 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 563 | 585 |
| 564 __ movp(rbx, Operand(rsp, 0)); // Get arguments count. | 586 // Get arguments count. |
| 565 } // Leave construct frame. | 587 __ movp(rbx, Operand(rsp, 0 * kPointerSize)); |
| 588 |
| 589 // Leave construct frame. |
| 590 } |
| 566 | 591 |
| 567 // Remove caller arguments from the stack and return. | 592 // Remove caller arguments from the stack and return. |
| 568 __ PopReturnAddressTo(rcx); | 593 __ PopReturnAddressTo(rcx); |
| 569 SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2); | 594 SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2); |
| 570 __ leap(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize)); | 595 __ leap(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize)); |
| 571 __ PushReturnAddressFrom(rcx); | 596 __ PushReturnAddressFrom(rcx); |
| 572 __ ret(0); | 597 __ ret(0); |
| 573 } | 598 } |
| 574 | 599 |
| 575 | 600 |
| (...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1325 masm, kArgumentsOffset, kIndexOffset, kLimitOffset); | 1350 masm, kArgumentsOffset, kIndexOffset, kLimitOffset); |
| 1326 | 1351 |
| 1327 // Use undefined feedback vector | 1352 // Use undefined feedback vector |
| 1328 __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex); | 1353 __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex); |
| 1329 __ movp(rdi, Operand(rbp, kFunctionOffset)); | 1354 __ movp(rdi, Operand(rbp, kFunctionOffset)); |
| 1330 | 1355 |
| 1331 // Call the function. | 1356 // Call the function. |
| 1332 CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL); | 1357 CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL); |
| 1333 __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); | 1358 __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); |
| 1334 | 1359 |
| 1360 // TODO(arv): Double check this drop. |
| 1335 __ Drop(1); | 1361 __ Drop(1); |
| 1336 | 1362 |
| 1337 // Leave internal frame. | 1363 // Leave internal frame. |
| 1338 } | 1364 } |
| 1339 // remove this, target, arguments and newTarget | 1365 // remove this, target, arguments and newTarget |
| 1340 __ ret(kStackSize * kPointerSize); | 1366 __ ret(kStackSize * kPointerSize); |
| 1341 } | 1367 } |
| 1342 | 1368 |
| 1343 | 1369 |
| 1344 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { | 1370 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { |
| (...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1751 __ bind(&ok); | 1777 __ bind(&ok); |
| 1752 __ ret(0); | 1778 __ ret(0); |
| 1753 } | 1779 } |
| 1754 | 1780 |
| 1755 | 1781 |
| 1756 #undef __ | 1782 #undef __ |
| 1757 | 1783 |
| 1758 } } // namespace v8::internal | 1784 } } // namespace v8::internal |
| 1759 | 1785 |
| 1760 #endif // V8_TARGET_ARCH_X64 | 1786 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |