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 "v8.h" | 5 #include "v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "code-stubs.h" | 9 #include "code-stubs.h" |
10 #include "codegen.h" | 10 #include "codegen.h" |
(...skipping 2536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2547 | 2547 |
2548 | 2548 |
2549 void FullCodeGenerator::CallIC(Handle<Code> code, | 2549 void FullCodeGenerator::CallIC(Handle<Code> code, |
2550 TypeFeedbackId ast_id) { | 2550 TypeFeedbackId ast_id) { |
2551 ic_total_count_++; | 2551 ic_total_count_++; |
2552 __ call(code, RelocInfo::CODE_TARGET, ast_id); | 2552 __ call(code, RelocInfo::CODE_TARGET, ast_id); |
2553 } | 2553 } |
2554 | 2554 |
2555 | 2555 |
2556 // Code common for calls using the IC. | 2556 // Code common for calls using the IC. |
2557 void FullCodeGenerator::EmitCallWithIC(Call* expr) { | 2557 void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) { |
2558 Expression* callee = expr->expression(); | 2558 Expression* callee = expr->expression(); |
2559 ZoneList<Expression*>* args = expr->arguments(); | |
2560 int arg_count = args->length(); | |
2561 | 2559 |
2562 CallFunctionFlags flags; | 2560 CallIC::CallType call_type = callee->IsVariableProxy() |
2563 // Get the target function; | 2561 ? CallIC::FUNCTION |
2564 if (callee->IsVariableProxy()) { | 2562 : CallIC::METHOD; |
| 2563 // Get the target function. |
| 2564 if (call_type == CallIC::FUNCTION) { |
2565 { StackValueContext context(this); | 2565 { StackValueContext context(this); |
2566 EmitVariableLoad(callee->AsVariableProxy()); | 2566 EmitVariableLoad(callee->AsVariableProxy()); |
2567 PrepareForBailout(callee, NO_REGISTERS); | 2567 PrepareForBailout(callee, NO_REGISTERS); |
2568 } | 2568 } |
2569 // Push undefined as receiver. This is patched in the method prologue if it | 2569 // Push undefined as receiver. This is patched in the method prologue if it |
2570 // is a sloppy mode method. | 2570 // is a sloppy mode method. |
2571 __ Push(isolate()->factory()->undefined_value()); | 2571 __ Push(isolate()->factory()->undefined_value()); |
2572 flags = NO_CALL_FUNCTION_FLAGS; | |
2573 } else { | 2572 } else { |
2574 // Load the function from the receiver. | 2573 // Load the function from the receiver. |
2575 ASSERT(callee->IsProperty()); | 2574 ASSERT(callee->IsProperty()); |
2576 __ movp(rax, Operand(rsp, 0)); | 2575 __ movp(rax, Operand(rsp, 0)); |
2577 EmitNamedPropertyLoad(callee->AsProperty()); | 2576 EmitNamedPropertyLoad(callee->AsProperty()); |
2578 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2577 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
2579 // Push the target function under the receiver. | 2578 // Push the target function under the receiver. |
2580 __ Push(Operand(rsp, 0)); | 2579 __ Push(Operand(rsp, 0)); |
2581 __ movp(Operand(rsp, kPointerSize), rax); | 2580 __ movp(Operand(rsp, kPointerSize), rax); |
2582 flags = CALL_AS_METHOD; | |
2583 } | 2581 } |
2584 | 2582 |
2585 // Load the arguments. | 2583 EmitCall(expr, call_type); |
2586 { PreservePositionScope scope(masm()->positions_recorder()); | |
2587 for (int i = 0; i < arg_count; i++) { | |
2588 VisitForStackValue(args->at(i)); | |
2589 } | |
2590 } | |
2591 | |
2592 // Record source position for debugger. | |
2593 SetSourcePosition(expr->position()); | |
2594 CallFunctionStub stub(isolate(), arg_count, flags); | |
2595 __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); | |
2596 __ CallStub(&stub); | |
2597 | |
2598 RecordJSReturnSite(expr); | |
2599 | |
2600 // Restore context register. | |
2601 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | |
2602 | |
2603 context()->DropAndPlug(1, rax); | |
2604 } | 2584 } |
2605 | 2585 |
2606 | 2586 |
2607 // Common code for calls using the IC. | 2587 // Common code for calls using the IC. |
2608 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2588 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, |
2609 Expression* key) { | 2589 Expression* key) { |
2610 // Load the key. | 2590 // Load the key. |
2611 VisitForAccumulatorValue(key); | 2591 VisitForAccumulatorValue(key); |
2612 | 2592 |
2613 Expression* callee = expr->expression(); | 2593 Expression* callee = expr->expression(); |
2614 ZoneList<Expression*>* args = expr->arguments(); | |
2615 int arg_count = args->length(); | |
2616 | 2594 |
2617 // Load the function from the receiver. | 2595 // Load the function from the receiver. |
2618 ASSERT(callee->IsProperty()); | 2596 ASSERT(callee->IsProperty()); |
2619 __ movp(rdx, Operand(rsp, 0)); | 2597 __ movp(rdx, Operand(rsp, 0)); |
2620 EmitKeyedPropertyLoad(callee->AsProperty()); | 2598 EmitKeyedPropertyLoad(callee->AsProperty()); |
2621 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2599 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
2622 | 2600 |
2623 // Push the target function under the receiver. | 2601 // Push the target function under the receiver. |
2624 __ Push(Operand(rsp, 0)); | 2602 __ Push(Operand(rsp, 0)); |
2625 __ movp(Operand(rsp, kPointerSize), rax); | 2603 __ movp(Operand(rsp, kPointerSize), rax); |
2626 | 2604 |
2627 // Load the arguments. | 2605 EmitCall(expr, CallIC::METHOD); |
2628 { PreservePositionScope scope(masm()->positions_recorder()); | |
2629 for (int i = 0; i < arg_count; i++) { | |
2630 VisitForStackValue(args->at(i)); | |
2631 } | |
2632 } | |
2633 | |
2634 // Record source position for debugger. | |
2635 SetSourcePosition(expr->position()); | |
2636 CallFunctionStub stub(isolate(), arg_count, CALL_AS_METHOD); | |
2637 __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); | |
2638 __ CallStub(&stub); | |
2639 | |
2640 RecordJSReturnSite(expr); | |
2641 // Restore context register. | |
2642 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | |
2643 | |
2644 context()->DropAndPlug(1, rax); | |
2645 } | 2606 } |
2646 | 2607 |
2647 | 2608 |
2648 void FullCodeGenerator::EmitCallWithStub(Call* expr) { | 2609 void FullCodeGenerator::EmitCall(Call* expr, CallIC::CallType call_type) { |
2649 // Code common for calls using the call stub. | 2610 // Load the arguments. |
2650 ZoneList<Expression*>* args = expr->arguments(); | 2611 ZoneList<Expression*>* args = expr->arguments(); |
2651 int arg_count = args->length(); | 2612 int arg_count = args->length(); |
2652 { PreservePositionScope scope(masm()->positions_recorder()); | 2613 { PreservePositionScope scope(masm()->positions_recorder()); |
2653 for (int i = 0; i < arg_count; i++) { | 2614 for (int i = 0; i < arg_count; i++) { |
2654 VisitForStackValue(args->at(i)); | 2615 VisitForStackValue(args->at(i)); |
2655 } | 2616 } |
2656 } | 2617 } |
2657 // Record source position for debugger. | 2618 |
| 2619 // Record source position of the IC call. |
2658 SetSourcePosition(expr->position()); | 2620 SetSourcePosition(expr->position()); |
| 2621 Handle<Code> ic = CallIC::initialize_stub( |
| 2622 isolate(), arg_count, call_type); |
| 2623 __ Move(rdx, Smi::FromInt(expr->CallFeedbackSlot())); |
| 2624 __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); |
| 2625 // Don't assign a type feedback id to the IC, since type feedback is provided |
| 2626 // by the vector above. |
| 2627 CallIC(ic); |
2659 | 2628 |
2660 __ Move(rbx, FeedbackVector()); | 2629 RecordJSReturnSite(expr); |
2661 __ Move(rdx, Smi::FromInt(expr->CallFeedbackSlot())); | |
2662 | 2630 |
2663 // Record call targets in unoptimized code. | |
2664 CallFunctionStub stub(isolate(), arg_count, RECORD_CALL_TARGET); | |
2665 __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); | |
2666 __ CallStub(&stub); | |
2667 RecordJSReturnSite(expr); | |
2668 // Restore context register. | 2631 // Restore context register. |
2669 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2632 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
2670 // Discard the function left on TOS. | 2633 // Discard the function left on TOS. |
2671 context()->DropAndPlug(1, rax); | 2634 context()->DropAndPlug(1, rax); |
2672 } | 2635 } |
2673 | 2636 |
2674 | 2637 |
2675 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { | 2638 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { |
2676 // Push copy of the first argument or undefined if it doesn't exist. | 2639 // Push copy of the first argument or undefined if it doesn't exist. |
2677 if (arg_count > 0) { | 2640 if (arg_count > 0) { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2734 // Record source position for debugger. | 2697 // Record source position for debugger. |
2735 SetSourcePosition(expr->position()); | 2698 SetSourcePosition(expr->position()); |
2736 CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS); | 2699 CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS); |
2737 __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); | 2700 __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); |
2738 __ CallStub(&stub); | 2701 __ CallStub(&stub); |
2739 RecordJSReturnSite(expr); | 2702 RecordJSReturnSite(expr); |
2740 // Restore context register. | 2703 // Restore context register. |
2741 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2704 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
2742 context()->DropAndPlug(1, rax); | 2705 context()->DropAndPlug(1, rax); |
2743 } else if (call_type == Call::GLOBAL_CALL) { | 2706 } else if (call_type == Call::GLOBAL_CALL) { |
2744 EmitCallWithIC(expr); | 2707 EmitCallWithLoadIC(expr); |
2745 | 2708 |
2746 } else if (call_type == Call::LOOKUP_SLOT_CALL) { | 2709 } else if (call_type == Call::LOOKUP_SLOT_CALL) { |
2747 // Call to a lookup slot (dynamically introduced variable). | 2710 // Call to a lookup slot (dynamically introduced variable). |
2748 VariableProxy* proxy = callee->AsVariableProxy(); | 2711 VariableProxy* proxy = callee->AsVariableProxy(); |
2749 Label slow, done; | 2712 Label slow, done; |
2750 | 2713 |
2751 { PreservePositionScope scope(masm()->positions_recorder()); | 2714 { PreservePositionScope scope(masm()->positions_recorder()); |
2752 // Generate code for loading from variables potentially shadowed by | 2715 // Generate code for loading from variables potentially shadowed by |
2753 // eval-introduced variables. | 2716 // eval-introduced variables. |
2754 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); | 2717 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); |
(...skipping 16 matching lines...) Expand all Loading... |
2771 // Push function. | 2734 // Push function. |
2772 __ Push(rax); | 2735 __ Push(rax); |
2773 // The receiver is implicitly the global receiver. Indicate this by | 2736 // The receiver is implicitly the global receiver. Indicate this by |
2774 // passing the hole to the call function stub. | 2737 // passing the hole to the call function stub. |
2775 __ PushRoot(Heap::kUndefinedValueRootIndex); | 2738 __ PushRoot(Heap::kUndefinedValueRootIndex); |
2776 __ bind(&call); | 2739 __ bind(&call); |
2777 } | 2740 } |
2778 | 2741 |
2779 // The receiver is either the global receiver or an object found by | 2742 // The receiver is either the global receiver or an object found by |
2780 // LoadContextSlot. | 2743 // LoadContextSlot. |
2781 EmitCallWithStub(expr); | 2744 EmitCall(expr); |
2782 } else if (call_type == Call::PROPERTY_CALL) { | 2745 } else if (call_type == Call::PROPERTY_CALL) { |
2783 Property* property = callee->AsProperty(); | 2746 Property* property = callee->AsProperty(); |
2784 { PreservePositionScope scope(masm()->positions_recorder()); | 2747 { PreservePositionScope scope(masm()->positions_recorder()); |
2785 VisitForStackValue(property->obj()); | 2748 VisitForStackValue(property->obj()); |
2786 } | 2749 } |
2787 if (property->key()->IsPropertyName()) { | 2750 if (property->key()->IsPropertyName()) { |
2788 EmitCallWithIC(expr); | 2751 EmitCallWithLoadIC(expr); |
2789 } else { | 2752 } else { |
2790 EmitKeyedCallWithIC(expr, property->key()); | 2753 EmitKeyedCallWithLoadIC(expr, property->key()); |
2791 } | 2754 } |
2792 } else { | 2755 } else { |
2793 ASSERT(call_type == Call::OTHER_CALL); | 2756 ASSERT(call_type == Call::OTHER_CALL); |
2794 // Call to an arbitrary expression not handled specially above. | 2757 // Call to an arbitrary expression not handled specially above. |
2795 { PreservePositionScope scope(masm()->positions_recorder()); | 2758 { PreservePositionScope scope(masm()->positions_recorder()); |
2796 VisitForStackValue(callee); | 2759 VisitForStackValue(callee); |
2797 } | 2760 } |
2798 __ PushRoot(Heap::kUndefinedValueRootIndex); | 2761 __ PushRoot(Heap::kUndefinedValueRootIndex); |
2799 // Emit function call. | 2762 // Emit function call. |
2800 EmitCallWithStub(expr); | 2763 EmitCall(expr); |
2801 } | 2764 } |
2802 | 2765 |
2803 #ifdef DEBUG | 2766 #ifdef DEBUG |
2804 // RecordJSReturnSite should have been called. | 2767 // RecordJSReturnSite should have been called. |
2805 ASSERT(expr->return_is_recorded_); | 2768 ASSERT(expr->return_is_recorded_); |
2806 #endif | 2769 #endif |
2807 } | 2770 } |
2808 | 2771 |
2809 | 2772 |
2810 void FullCodeGenerator::VisitCallNew(CallNew* expr) { | 2773 void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
(...skipping 25 matching lines...) Expand all Loading... |
2836 // Record call targets in unoptimized code, but not in the snapshot. | 2799 // Record call targets in unoptimized code, but not in the snapshot. |
2837 if (FLAG_pretenuring_call_new) { | 2800 if (FLAG_pretenuring_call_new) { |
2838 EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); | 2801 EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); |
2839 ASSERT(expr->AllocationSiteFeedbackSlot() == | 2802 ASSERT(expr->AllocationSiteFeedbackSlot() == |
2840 expr->CallNewFeedbackSlot() + 1); | 2803 expr->CallNewFeedbackSlot() + 1); |
2841 } | 2804 } |
2842 | 2805 |
2843 __ Move(rbx, FeedbackVector()); | 2806 __ Move(rbx, FeedbackVector()); |
2844 __ Move(rdx, Smi::FromInt(expr->CallNewFeedbackSlot())); | 2807 __ Move(rdx, Smi::FromInt(expr->CallNewFeedbackSlot())); |
2845 | 2808 |
2846 CallConstructStub stub(isolate(), RECORD_CALL_TARGET); | 2809 CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); |
2847 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); | 2810 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); |
2848 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); | 2811 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); |
2849 context()->Plug(rax); | 2812 context()->Plug(rax); |
2850 } | 2813 } |
2851 | 2814 |
2852 | 2815 |
2853 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { | 2816 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { |
2854 ZoneList<Expression*>* args = expr->arguments(); | 2817 ZoneList<Expression*>* args = expr->arguments(); |
2855 ASSERT(args->length() == 1); | 2818 ASSERT(args->length() == 1); |
2856 | 2819 |
(...skipping 2034 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4891 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), | 4854 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), |
4892 Assembler::target_address_at(call_target_address, | 4855 Assembler::target_address_at(call_target_address, |
4893 unoptimized_code)); | 4856 unoptimized_code)); |
4894 return OSR_AFTER_STACK_CHECK; | 4857 return OSR_AFTER_STACK_CHECK; |
4895 } | 4858 } |
4896 | 4859 |
4897 | 4860 |
4898 } } // namespace v8::internal | 4861 } } // namespace v8::internal |
4899 | 4862 |
4900 #endif // V8_TARGET_ARCH_X64 | 4863 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |