| 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_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
| 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 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 538 Label loop_header, loop_check; | 538 Label loop_header, loop_check; |
| 539 __ jmp(&loop_check); | 539 __ jmp(&loop_check); |
| 540 __ bind(&loop_header); | 540 __ bind(&loop_header); |
| 541 __ Push(Operand(ebx, 0)); | 541 __ Push(Operand(ebx, 0)); |
| 542 __ sub(ebx, Immediate(kPointerSize)); | 542 __ sub(ebx, Immediate(kPointerSize)); |
| 543 __ bind(&loop_check); | 543 __ bind(&loop_check); |
| 544 __ cmp(ebx, array_limit); | 544 __ cmp(ebx, array_limit); |
| 545 __ j(greater, &loop_header, Label::kNear); | 545 __ j(greater, &loop_header, Label::kNear); |
| 546 } | 546 } |
| 547 | 547 |
| 548 static void Generate_InterpreterComputeLastArgumentAddress(MacroAssembler* masm, | |
| 549 Register r) { | |
| 550 // Find the address of the last argument. | |
| 551 // ----------- S t a t e ------------- | |
| 552 // input: eax : Number of arguments. | |
| 553 // input: ebx : Address of the first argument. | |
| 554 // output: Register |r|: Address of the last argument. | |
| 555 // ----------------------------------- | |
| 556 __ mov(r, eax); | |
| 557 __ add(r, Immediate(1)); // Add one for receiver. | |
| 558 __ shl(r, kPointerSizeLog2); | |
| 559 __ neg(r); | |
| 560 __ add(r, ebx); | |
| 561 } | |
| 562 | 548 |
| 563 // static | 549 // static |
| 564 void Builtins::Generate_InterpreterPushArgsAndCallICImpl( | 550 void Builtins::Generate_InterpreterPushArgsAndCallImpl( |
| 565 MacroAssembler* masm, TailCallMode tail_call_mode) { | 551 MacroAssembler* masm, TailCallMode tail_call_mode) { |
| 566 // ----------- S t a t e ------------- | 552 // ----------- S t a t e ------------- |
| 567 // -- eax : the number of arguments (not including the receiver) | 553 // -- eax : the number of arguments (not including the receiver) |
| 568 // -- ebx : the address of the first argument to be pushed. Subsequent | 554 // -- ebx : the address of the first argument to be pushed. Subsequent |
| 569 // arguments should be consecutive above this, in the same order as | 555 // arguments should be consecutive above this, in the same order as |
| 570 // they are to be pushed onto the stack. | 556 // they are to be pushed onto the stack. |
| 571 // -- edi : the target to call (can be any Object). | 557 // -- edi : the target to call (can be any Object). |
| 572 // -- edx : feedback slot id. | |
| 573 // -- ecx : type feedback vector. | |
| 574 // ----------------------------------- | |
| 575 | |
| 576 { | |
| 577 FrameScope scope(masm, StackFrame::INTERNAL); | |
| 578 // Store type feedback vector on the stack since we ran out of registers. | |
| 579 __ Push(ecx); | |
| 580 | |
| 581 // computes the address of last argument in ecx. | |
| 582 // ecx = ebx - (eax + 1) * kPointerSize. | |
| 583 Generate_InterpreterComputeLastArgumentAddress(masm, ecx); | |
| 584 Generate_InterpreterPushArgs(masm, ecx); | |
| 585 | |
| 586 // Restore feedback vector to ebx from the stack. It was pushed | |
| 587 // before the arguments were pushed, so compute the correct offset. | |
| 588 __ mov(ebx, Operand(esp, eax, times_pointer_size, 1 * kPointerSize)); | |
| 589 | |
| 590 // Call via the CallIC stub. | |
| 591 CallICState call_ic_state(0, ConvertReceiverMode::kAny, tail_call_mode, | |
| 592 true); | |
| 593 CallICStub stub(masm->isolate(), call_ic_state); | |
| 594 // TODO(mythria): This should be replaced by a TailCallStub, when we | |
| 595 // update the code to find the target IC from jump instructions. | |
| 596 __ CallStub(&stub); | |
| 597 } | |
| 598 __ Ret(); | |
| 599 } | |
| 600 | |
| 601 // static | |
| 602 void Builtins::Generate_InterpreterPushArgsAndCallImpl( | |
| 603 MacroAssembler* masm, TailCallMode tail_call_mode) { | |
| 604 // ----------- S t a t e ------------- | |
| 605 // -- eax : the number of arguments (not including the receiver) | |
| 606 // -- ebx : the address of the first argument to be pushed. Subsequent | |
| 607 // arguments should be consecutive above this, in the same order as | |
| 608 // they are to be pushed onto the stack. | |
| 609 // -- edi : the target to call (can be any Object). | |
| 610 // ----------------------------------- | 558 // ----------------------------------- |
| 611 | 559 |
| 612 // Pop return address to allow tail-call after pushing arguments. | 560 // Pop return address to allow tail-call after pushing arguments. |
| 613 __ Pop(edx); | 561 __ Pop(edx); |
| 614 | 562 |
| 615 // computes the address of last argument in ecx. | 563 // Find the address of the last argument. |
| 616 // ecx = ebx - (eax + 1) * kPointerSize. | 564 __ mov(ecx, eax); |
| 617 Generate_InterpreterComputeLastArgumentAddress(masm, ecx); | 565 __ add(ecx, Immediate(1)); // Add one for receiver. |
| 566 __ shl(ecx, kPointerSizeLog2); |
| 567 __ neg(ecx); |
| 568 __ add(ecx, ebx); |
| 569 |
| 618 Generate_InterpreterPushArgs(masm, ecx); | 570 Generate_InterpreterPushArgs(masm, ecx); |
| 619 | 571 |
| 620 // Call the target. | 572 // Call the target. |
| 621 __ Push(edx); // Re-push return address. | 573 __ Push(edx); // Re-push return address. |
| 622 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, | 574 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, |
| 623 tail_call_mode), | 575 tail_call_mode), |
| 624 RelocInfo::CODE_TARGET); | 576 RelocInfo::CODE_TARGET); |
| 625 } | 577 } |
| 626 | 578 |
| 579 |
| 627 // static | 580 // static |
| 628 void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) { | 581 void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) { |
| 629 // ----------- S t a t e ------------- | 582 // ----------- S t a t e ------------- |
| 630 // -- eax : the number of arguments (not including the receiver) | 583 // -- eax : the number of arguments (not including the receiver) |
| 631 // -- edx : the new target | 584 // -- edx : the new target |
| 632 // -- edi : the constructor | 585 // -- edi : the constructor |
| 633 // -- ebx : the address of the first argument to be pushed. Subsequent | 586 // -- ebx : the address of the first argument to be pushed. Subsequent |
| 634 // arguments should be consecutive above this, in the same order as | 587 // arguments should be consecutive above this, in the same order as |
| 635 // they are to be pushed onto the stack. | 588 // they are to be pushed onto the stack. |
| 636 // ----------------------------------- | 589 // ----------------------------------- |
| 637 | 590 |
| 591 // Save number of arguments on the stack below where arguments are going |
| 592 // to be pushed. |
| 593 __ mov(ecx, eax); |
| 594 __ neg(ecx); |
| 595 __ mov(Operand(esp, ecx, times_pointer_size, -kPointerSize), eax); |
| 596 __ mov(eax, ecx); |
| 597 |
| 638 // Pop return address to allow tail-call after pushing arguments. | 598 // Pop return address to allow tail-call after pushing arguments. |
| 639 __ Pop(ecx); | 599 __ Pop(ecx); |
| 640 | 600 |
| 641 // Push edi in the slot meant for receiver. We need an extra register so | 601 // Find the address of the last argument. |
| 642 // store edi temporarily on the stack. | 602 __ shl(eax, kPointerSizeLog2); |
| 643 __ Push(edi); | 603 __ add(eax, ebx); |
| 644 | 604 |
| 645 // Find the address of the last argument. | 605 // Push padding for receiver. |
| 646 __ mov(edi, eax); | 606 __ Push(Immediate(0)); |
| 647 __ neg(edi); | |
| 648 __ shl(edi, kPointerSizeLog2); | |
| 649 __ add(edi, ebx); | |
| 650 | 607 |
| 651 Generate_InterpreterPushArgs(masm, edi); | 608 Generate_InterpreterPushArgs(masm, eax); |
| 652 | 609 |
| 653 // Restore number of arguments from slot on stack. edi was pushed at | 610 // Restore number of arguments from slot on stack. |
| 654 // the slot meant for receiver. | 611 __ mov(eax, Operand(esp, -kPointerSize)); |
| 655 __ mov(edi, Operand(esp, eax, times_pointer_size, 0)); | |
| 656 | 612 |
| 657 // Re-push return address. | 613 // Re-push return address. |
| 658 __ Push(ecx); | 614 __ Push(ecx); |
| 659 | 615 |
| 660 // Call the constructor with unmodified eax, edi, ebi values. | 616 // Call the constructor with unmodified eax, edi, ebi values. |
| 661 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 617 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
| 662 } | 618 } |
| 663 | 619 |
| 664 | 620 |
| 665 static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) { | 621 static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) { |
| (...skipping 1230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1896 Comment cmnt(masm, "[ PrepareForTailCall"); | 1852 Comment cmnt(masm, "[ PrepareForTailCall"); |
| 1897 | 1853 |
| 1898 // Prepare for tail call only if the debugger is not active. | 1854 // Prepare for tail call only if the debugger is not active. |
| 1899 Label done; | 1855 Label done; |
| 1900 ExternalReference debug_is_active = | 1856 ExternalReference debug_is_active = |
| 1901 ExternalReference::debug_is_active_address(masm->isolate()); | 1857 ExternalReference::debug_is_active_address(masm->isolate()); |
| 1902 __ movzx_b(scratch1, Operand::StaticVariable(debug_is_active)); | 1858 __ movzx_b(scratch1, Operand::StaticVariable(debug_is_active)); |
| 1903 __ cmp(scratch1, Immediate(0)); | 1859 __ cmp(scratch1, Immediate(0)); |
| 1904 __ j(not_equal, &done, Label::kNear); | 1860 __ j(not_equal, &done, Label::kNear); |
| 1905 | 1861 |
| 1906 // Drop possible internal frame pushed for calling CallICStub. | |
| 1907 // TODO(mythria): when we tail call the CallICStub, remove this. | |
| 1908 { | |
| 1909 Label no_internal_callic_frame; | |
| 1910 __ cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset), | |
| 1911 Immediate(Smi::FromInt(StackFrame::INTERNAL))); | |
| 1912 __ j(not_equal, &no_internal_callic_frame, Label::kNear); | |
| 1913 __ mov(ebp, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | |
| 1914 __ bind(&no_internal_callic_frame); | |
| 1915 } | |
| 1916 | |
| 1917 // Drop possible interpreter handler/stub frame. | 1862 // Drop possible interpreter handler/stub frame. |
| 1918 { | 1863 { |
| 1919 Label no_interpreter_frame; | 1864 Label no_interpreter_frame; |
| 1920 __ cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset), | 1865 __ cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset), |
| 1921 Immediate(Smi::FromInt(StackFrame::STUB))); | 1866 Immediate(Smi::FromInt(StackFrame::STUB))); |
| 1922 __ j(not_equal, &no_interpreter_frame, Label::kNear); | 1867 __ j(not_equal, &no_interpreter_frame, Label::kNear); |
| 1923 __ mov(ebp, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 1868 __ mov(ebp, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| 1924 __ bind(&no_interpreter_frame); | 1869 __ bind(&no_interpreter_frame); |
| 1925 } | 1870 } |
| 1926 | 1871 |
| (...skipping 777 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2704 | 2649 |
| 2705 __ bind(&ok); | 2650 __ bind(&ok); |
| 2706 __ ret(0); | 2651 __ ret(0); |
| 2707 } | 2652 } |
| 2708 | 2653 |
| 2709 #undef __ | 2654 #undef __ |
| 2710 } // namespace internal | 2655 } // namespace internal |
| 2711 } // namespace v8 | 2656 } // namespace v8 |
| 2712 | 2657 |
| 2713 #endif // V8_TARGET_ARCH_IA32 | 2658 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |