Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(158)

Side by Side Diff: src/ia32/full-codegen-ia32.cc

Issue 224903005: Reland "create a function call IC" (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Comments. Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/debug-ia32.cc ('k') | src/ia32/lithium-codegen-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 2564 matching lines...) Expand 10 before | Expand all | Expand 10 after
2575 } 2575 }
2576 2576
2577 2577
2578 void FullCodeGenerator::CallIC(Handle<Code> code, 2578 void FullCodeGenerator::CallIC(Handle<Code> code,
2579 TypeFeedbackId ast_id) { 2579 TypeFeedbackId ast_id) {
2580 ic_total_count_++; 2580 ic_total_count_++;
2581 __ call(code, RelocInfo::CODE_TARGET, ast_id); 2581 __ call(code, RelocInfo::CODE_TARGET, ast_id);
2582 } 2582 }
2583 2583
2584 2584
2585 // Code common for calls using the IC.
2586 void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
2587 Expression* callee = expr->expression();
2585 2588
2586 2589 CallIC::CallType call_type = callee->IsVariableProxy()
2587 // Code common for calls using the IC. 2590 ? CallIC::FUNCTION
2588 void FullCodeGenerator::EmitCallWithIC(Call* expr) { 2591 : CallIC::METHOD;
2589 Expression* callee = expr->expression();
2590 ZoneList<Expression*>* args = expr->arguments();
2591 int arg_count = args->length();
2592
2593 CallFunctionFlags flags;
2594 // Get the target function. 2592 // Get the target function.
2595 if (callee->IsVariableProxy()) { 2593 if (call_type == CallIC::FUNCTION) {
2596 { StackValueContext context(this); 2594 { StackValueContext context(this);
2597 EmitVariableLoad(callee->AsVariableProxy()); 2595 EmitVariableLoad(callee->AsVariableProxy());
2598 PrepareForBailout(callee, NO_REGISTERS); 2596 PrepareForBailout(callee, NO_REGISTERS);
2599 } 2597 }
2600 // Push undefined as receiver. This is patched in the method prologue if it 2598 // Push undefined as receiver. This is patched in the method prologue if it
2601 // is a sloppy mode method. 2599 // is a sloppy mode method.
2602 __ push(Immediate(isolate()->factory()->undefined_value())); 2600 __ push(Immediate(isolate()->factory()->undefined_value()));
2603 flags = NO_CALL_FUNCTION_FLAGS;
2604 } else { 2601 } else {
2605 // Load the function from the receiver. 2602 // Load the function from the receiver.
2606 ASSERT(callee->IsProperty()); 2603 ASSERT(callee->IsProperty());
2607 __ mov(edx, Operand(esp, 0)); 2604 __ mov(edx, Operand(esp, 0));
2608 EmitNamedPropertyLoad(callee->AsProperty()); 2605 EmitNamedPropertyLoad(callee->AsProperty());
2609 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); 2606 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2610 // Push the target function under the receiver. 2607 // Push the target function under the receiver.
2611 __ push(Operand(esp, 0)); 2608 __ push(Operand(esp, 0));
2612 __ mov(Operand(esp, kPointerSize), eax); 2609 __ mov(Operand(esp, kPointerSize), eax);
2613 flags = CALL_AS_METHOD;
2614 } 2610 }
2615 2611
2616 // Load the arguments. 2612 EmitCall(expr, call_type);
2617 { PreservePositionScope scope(masm()->positions_recorder());
2618 for (int i = 0; i < arg_count; i++) {
2619 VisitForStackValue(args->at(i));
2620 }
2621 }
2622
2623 // Record source position of the IC call.
2624 SetSourcePosition(expr->position());
2625 CallFunctionStub stub(arg_count, flags);
2626 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
2627 __ CallStub(&stub);
2628 RecordJSReturnSite(expr);
2629
2630 // Restore context register.
2631 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2632
2633 context()->DropAndPlug(1, eax);
2634 } 2613 }
2635 2614
2636 2615
2637 // Code common for calls using the IC. 2616 // Code common for calls using the IC.
2638 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, 2617 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
2639 Expression* key) { 2618 Expression* key) {
2640 // Load the key. 2619 // Load the key.
2641 VisitForAccumulatorValue(key); 2620 VisitForAccumulatorValue(key);
2642 2621
2643 Expression* callee = expr->expression(); 2622 Expression* callee = expr->expression();
2644 ZoneList<Expression*>* args = expr->arguments();
2645 int arg_count = args->length();
2646 2623
2647 // Load the function from the receiver. 2624 // Load the function from the receiver.
2648 ASSERT(callee->IsProperty()); 2625 ASSERT(callee->IsProperty());
2649 __ mov(edx, Operand(esp, 0)); 2626 __ mov(edx, Operand(esp, 0));
2650 // Move the key into the right register for the keyed load IC. 2627 // Move the key into the right register for the keyed load IC.
2651 __ mov(ecx, eax); 2628 __ mov(ecx, eax);
2652 EmitKeyedPropertyLoad(callee->AsProperty()); 2629 EmitKeyedPropertyLoad(callee->AsProperty());
2653 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); 2630 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2654 2631
2655 // Push the target function under the receiver. 2632 // Push the target function under the receiver.
2656 __ push(Operand(esp, 0)); 2633 __ push(Operand(esp, 0));
2657 __ mov(Operand(esp, kPointerSize), eax); 2634 __ mov(Operand(esp, kPointerSize), eax);
2658 2635
2659 // Load the arguments. 2636 EmitCall(expr, CallIC::METHOD);
2660 { PreservePositionScope scope(masm()->positions_recorder());
2661 for (int i = 0; i < arg_count; i++) {
2662 VisitForStackValue(args->at(i));
2663 }
2664 }
2665
2666 // Record source position of the IC call.
2667 SetSourcePosition(expr->position());
2668 CallFunctionStub stub(arg_count, CALL_AS_METHOD);
2669 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
2670 __ CallStub(&stub);
2671 RecordJSReturnSite(expr);
2672
2673 // Restore context register.
2674 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2675
2676 context()->DropAndPlug(1, eax);
2677 } 2637 }
2678 2638
2679 2639
2680 void FullCodeGenerator::EmitCallWithStub(Call* expr) { 2640 void FullCodeGenerator::EmitCall(Call* expr, CallIC::CallType call_type) {
2681 // Code common for calls using the call stub. 2641 // Load the arguments.
2682 ZoneList<Expression*>* args = expr->arguments(); 2642 ZoneList<Expression*>* args = expr->arguments();
2683 int arg_count = args->length(); 2643 int arg_count = args->length();
2684 { PreservePositionScope scope(masm()->positions_recorder()); 2644 { PreservePositionScope scope(masm()->positions_recorder());
2685 for (int i = 0; i < arg_count; i++) { 2645 for (int i = 0; i < arg_count; i++) {
2686 VisitForStackValue(args->at(i)); 2646 VisitForStackValue(args->at(i));
2687 } 2647 }
2688 } 2648 }
2689 // Record source position for debugger. 2649
2650 // Record source position of the IC call.
2690 SetSourcePosition(expr->position()); 2651 SetSourcePosition(expr->position());
2691 2652 Handle<Code> ic = CallIC::initialize_stub(
2653 isolate(), arg_count, call_type);
2692 Handle<Object> uninitialized = 2654 Handle<Object> uninitialized =
2693 TypeFeedbackInfo::UninitializedSentinel(isolate()); 2655 TypeFeedbackInfo::UninitializedSentinel(isolate());
2694 StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized); 2656 StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized);
2695 __ LoadHeapObject(ebx, FeedbackVector()); 2657 __ LoadHeapObject(ebx, FeedbackVector());
2696 __ mov(edx, Immediate(Smi::FromInt(expr->CallFeedbackSlot()))); 2658 __ mov(edx, Immediate(Smi::FromInt(expr->CallFeedbackSlot())));
2697
2698 // Record call targets in unoptimized code.
2699 CallFunctionStub stub(arg_count, RECORD_CALL_TARGET);
2700 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); 2659 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
2701 __ CallStub(&stub); 2660 // Don't assign a type feedback id to the IC, since type feedback is provided
2661 // by the vector above.
2662 CallIC(ic);
2702 2663
2703 RecordJSReturnSite(expr); 2664 RecordJSReturnSite(expr);
2665
2704 // Restore context register. 2666 // Restore context register.
2705 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2667 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2668
2706 context()->DropAndPlug(1, eax); 2669 context()->DropAndPlug(1, eax);
2707 } 2670 }
2708 2671
2709 2672
2710 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { 2673 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
2711 // Push copy of the first argument or undefined if it doesn't exist. 2674 // Push copy of the first argument or undefined if it doesn't exist.
2712 if (arg_count > 0) { 2675 if (arg_count > 0) {
2713 __ push(Operand(esp, arg_count * kPointerSize)); 2676 __ push(Operand(esp, arg_count * kPointerSize));
2714 } else { 2677 } else {
2715 __ push(Immediate(isolate()->factory()->undefined_value())); 2678 __ push(Immediate(isolate()->factory()->undefined_value()));
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2768 SetSourcePosition(expr->position()); 2731 SetSourcePosition(expr->position());
2769 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS); 2732 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS);
2770 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); 2733 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
2771 __ CallStub(&stub); 2734 __ CallStub(&stub);
2772 RecordJSReturnSite(expr); 2735 RecordJSReturnSite(expr);
2773 // Restore context register. 2736 // Restore context register.
2774 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2737 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2775 context()->DropAndPlug(1, eax); 2738 context()->DropAndPlug(1, eax);
2776 2739
2777 } else if (call_type == Call::GLOBAL_CALL) { 2740 } else if (call_type == Call::GLOBAL_CALL) {
2778 EmitCallWithIC(expr); 2741 EmitCallWithLoadIC(expr);
2779 2742
2780 } else if (call_type == Call::LOOKUP_SLOT_CALL) { 2743 } else if (call_type == Call::LOOKUP_SLOT_CALL) {
2781 // Call to a lookup slot (dynamically introduced variable). 2744 // Call to a lookup slot (dynamically introduced variable).
2782 VariableProxy* proxy = callee->AsVariableProxy(); 2745 VariableProxy* proxy = callee->AsVariableProxy();
2783 Label slow, done; 2746 Label slow, done;
2784 { PreservePositionScope scope(masm()->positions_recorder()); 2747 { PreservePositionScope scope(masm()->positions_recorder());
2785 // Generate code for loading from variables potentially shadowed by 2748 // Generate code for loading from variables potentially shadowed by
2786 // eval-introduced variables. 2749 // eval-introduced variables.
2787 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); 2750 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done);
2788 } 2751 }
(...skipping 15 matching lines...) Expand all
2804 // Push function. 2767 // Push function.
2805 __ push(eax); 2768 __ push(eax);
2806 // The receiver is implicitly the global receiver. Indicate this by 2769 // The receiver is implicitly the global receiver. Indicate this by
2807 // passing the hole to the call function stub. 2770 // passing the hole to the call function stub.
2808 __ push(Immediate(isolate()->factory()->undefined_value())); 2771 __ push(Immediate(isolate()->factory()->undefined_value()));
2809 __ bind(&call); 2772 __ bind(&call);
2810 } 2773 }
2811 2774
2812 // The receiver is either the global receiver or an object found by 2775 // The receiver is either the global receiver or an object found by
2813 // LoadContextSlot. 2776 // LoadContextSlot.
2814 EmitCallWithStub(expr); 2777 EmitCall(expr);
2815 2778
2816 } else if (call_type == Call::PROPERTY_CALL) { 2779 } else if (call_type == Call::PROPERTY_CALL) {
2817 Property* property = callee->AsProperty(); 2780 Property* property = callee->AsProperty();
2818 { PreservePositionScope scope(masm()->positions_recorder()); 2781 { PreservePositionScope scope(masm()->positions_recorder());
2819 VisitForStackValue(property->obj()); 2782 VisitForStackValue(property->obj());
2820 } 2783 }
2821 if (property->key()->IsPropertyName()) { 2784 if (property->key()->IsPropertyName()) {
2822 EmitCallWithIC(expr); 2785 EmitCallWithLoadIC(expr);
2823 } else { 2786 } else {
2824 EmitKeyedCallWithIC(expr, property->key()); 2787 EmitKeyedCallWithLoadIC(expr, property->key());
2825 } 2788 }
2826 2789
2827 } else { 2790 } else {
2828 ASSERT(call_type == Call::OTHER_CALL); 2791 ASSERT(call_type == Call::OTHER_CALL);
2829 // Call to an arbitrary expression not handled specially above. 2792 // Call to an arbitrary expression not handled specially above.
2830 { PreservePositionScope scope(masm()->positions_recorder()); 2793 { PreservePositionScope scope(masm()->positions_recorder());
2831 VisitForStackValue(callee); 2794 VisitForStackValue(callee);
2832 } 2795 }
2833 __ push(Immediate(isolate()->factory()->undefined_value())); 2796 __ push(Immediate(isolate()->factory()->undefined_value()));
2834 // Emit function call. 2797 // Emit function call.
2835 EmitCallWithStub(expr); 2798 EmitCall(expr);
2836 } 2799 }
2837 2800
2838 #ifdef DEBUG 2801 #ifdef DEBUG
2839 // RecordJSReturnSite should have been called. 2802 // RecordJSReturnSite should have been called.
2840 ASSERT(expr->return_is_recorded_); 2803 ASSERT(expr->return_is_recorded_);
2841 #endif 2804 #endif
2842 } 2805 }
2843 2806
2844 2807
2845 void FullCodeGenerator::VisitCallNew(CallNew* expr) { 2808 void FullCodeGenerator::VisitCallNew(CallNew* expr) {
(...skipping 29 matching lines...) Expand all
2875 if (FLAG_pretenuring_call_new) { 2838 if (FLAG_pretenuring_call_new) {
2876 StoreFeedbackVectorSlot(expr->AllocationSiteFeedbackSlot(), 2839 StoreFeedbackVectorSlot(expr->AllocationSiteFeedbackSlot(),
2877 isolate()->factory()->NewAllocationSite()); 2840 isolate()->factory()->NewAllocationSite());
2878 ASSERT(expr->AllocationSiteFeedbackSlot() == 2841 ASSERT(expr->AllocationSiteFeedbackSlot() ==
2879 expr->CallNewFeedbackSlot() + 1); 2842 expr->CallNewFeedbackSlot() + 1);
2880 } 2843 }
2881 2844
2882 __ LoadHeapObject(ebx, FeedbackVector()); 2845 __ LoadHeapObject(ebx, FeedbackVector());
2883 __ mov(edx, Immediate(Smi::FromInt(expr->CallNewFeedbackSlot()))); 2846 __ mov(edx, Immediate(Smi::FromInt(expr->CallNewFeedbackSlot())));
2884 2847
2885 CallConstructStub stub(RECORD_CALL_TARGET); 2848 CallConstructStub stub(RECORD_CONSTRUCTOR_TARGET);
2886 __ call(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL); 2849 __ call(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL);
2887 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); 2850 PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
2888 context()->Plug(eax); 2851 context()->Plug(eax);
2889 } 2852 }
2890 2853
2891 2854
2892 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { 2855 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
2893 ZoneList<Expression*>* args = expr->arguments(); 2856 ZoneList<Expression*>* args = expr->arguments();
2894 ASSERT(args->length() == 1); 2857 ASSERT(args->length() == 1);
2895 2858
(...skipping 2022 matching lines...) Expand 10 before | Expand all | Expand 10 after
4918 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), 4881 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(),
4919 Assembler::target_address_at(call_target_address, 4882 Assembler::target_address_at(call_target_address,
4920 unoptimized_code)); 4883 unoptimized_code));
4921 return OSR_AFTER_STACK_CHECK; 4884 return OSR_AFTER_STACK_CHECK;
4922 } 4885 }
4923 4886
4924 4887
4925 } } // namespace v8::internal 4888 } } // namespace v8::internal
4926 4889
4927 #endif // V8_TARGET_ARCH_IA32 4890 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/debug-ia32.cc ('k') | src/ia32/lithium-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698