| 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 |