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 |