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

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

Issue 172523002: Create a function call IC (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Comments addressed. Created 6 years, 9 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
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 2541 matching lines...) Expand 10 before | Expand all | Expand 10 after
2552 } 2552 }
2553 2553
2554 2554
2555 void FullCodeGenerator::CallIC(Handle<Code> code, 2555 void FullCodeGenerator::CallIC(Handle<Code> code,
2556 TypeFeedbackId ast_id) { 2556 TypeFeedbackId ast_id) {
2557 ic_total_count_++; 2557 ic_total_count_++;
2558 __ call(code, RelocInfo::CODE_TARGET, ast_id); 2558 __ call(code, RelocInfo::CODE_TARGET, ast_id);
2559 } 2559 }
2560 2560
2561 2561
2562 // Code common for calls using the IC.
2563 void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
2564 Expression* callee = expr->expression();
2562 2565
2563 2566 CallIC::CallType call_type = callee->IsVariableProxy()
2564 // Code common for calls using the IC. 2567 ? CallIC::FUNCTION
2565 void FullCodeGenerator::EmitCallWithIC(Call* expr) { 2568 : CallIC::METHOD;
2566 Expression* callee = expr->expression();
2567 ZoneList<Expression*>* args = expr->arguments();
2568 int arg_count = args->length();
2569
2570 CallFunctionFlags flags;
2571 // Get the target function. 2569 // Get the target function.
2572 if (callee->IsVariableProxy()) { 2570 if (call_type == CallIC::FUNCTION) {
2573 { StackValueContext context(this); 2571 { StackValueContext context(this);
2574 EmitVariableLoad(callee->AsVariableProxy()); 2572 EmitVariableLoad(callee->AsVariableProxy());
2575 PrepareForBailout(callee, NO_REGISTERS); 2573 PrepareForBailout(callee, NO_REGISTERS);
2576 } 2574 }
2577 // Push undefined as receiver. This is patched in the method prologue if it 2575 // Push undefined as receiver. This is patched in the method prologue if it
2578 // is a classic mode method. 2576 // is a classic mode method.
2579 __ push(Immediate(isolate()->factory()->undefined_value())); 2577 __ push(Immediate(isolate()->factory()->undefined_value()));
2580 flags = NO_CALL_FUNCTION_FLAGS;
2581 } else { 2578 } else {
2582 // Load the function from the receiver. 2579 // Load the function from the receiver.
2583 ASSERT(callee->IsProperty()); 2580 ASSERT(callee->IsProperty());
2584 __ mov(edx, Operand(esp, 0)); 2581 __ mov(edx, Operand(esp, 0));
2585 EmitNamedPropertyLoad(callee->AsProperty()); 2582 EmitNamedPropertyLoad(callee->AsProperty());
2586 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); 2583 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2587 // Push the target function under the receiver. 2584 // Push the target function under the receiver.
2588 __ push(Operand(esp, 0)); 2585 __ push(Operand(esp, 0));
2589 __ mov(Operand(esp, kPointerSize), eax); 2586 __ mov(Operand(esp, kPointerSize), eax);
2590 flags = CALL_AS_METHOD;
2591 } 2587 }
2592 2588
2593 // Load the arguments. 2589 EmitCall(expr, call_type);
2594 { PreservePositionScope scope(masm()->positions_recorder());
2595 for (int i = 0; i < arg_count; i++) {
2596 VisitForStackValue(args->at(i));
2597 }
2598 }
2599
2600 // Record source position of the IC call.
2601 SetSourcePosition(expr->position());
2602 CallFunctionStub stub(arg_count, flags);
2603 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
2604 __ CallStub(&stub);
2605 RecordJSReturnSite(expr);
2606
2607 // Restore context register.
2608 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2609
2610 context()->DropAndPlug(1, eax);
2611 } 2590 }
2612 2591
2613 2592
2614 // Code common for calls using the IC. 2593 // Code common for calls using the IC.
2615 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, 2594 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
2616 Expression* key) { 2595 Expression* key) {
2617 // Load the key. 2596 // Load the key.
2618 VisitForAccumulatorValue(key); 2597 VisitForAccumulatorValue(key);
2619 2598
2620 Expression* callee = expr->expression(); 2599 Expression* callee = expr->expression();
2621 ZoneList<Expression*>* args = expr->arguments();
2622 int arg_count = args->length();
2623 2600
2624 // Load the function from the receiver. 2601 // Load the function from the receiver.
2625 ASSERT(callee->IsProperty()); 2602 ASSERT(callee->IsProperty());
2626 __ mov(edx, Operand(esp, 0)); 2603 __ mov(edx, Operand(esp, 0));
2627 // Move the key into the right register for the keyed load IC. 2604 // Move the key into the right register for the keyed load IC.
2628 __ mov(ecx, eax); 2605 __ mov(ecx, eax);
2629 EmitKeyedPropertyLoad(callee->AsProperty()); 2606 EmitKeyedPropertyLoad(callee->AsProperty());
2630 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); 2607 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2631 2608
2632 // Push the target function under the receiver. 2609 // Push the target function under the receiver.
2633 __ push(Operand(esp, 0)); 2610 __ push(Operand(esp, 0));
2634 __ mov(Operand(esp, kPointerSize), eax); 2611 __ mov(Operand(esp, kPointerSize), eax);
2635 2612
2636 // Load the arguments. 2613 EmitCall(expr, CallIC::METHOD);
2637 { PreservePositionScope scope(masm()->positions_recorder());
2638 for (int i = 0; i < arg_count; i++) {
2639 VisitForStackValue(args->at(i));
2640 }
2641 }
2642
2643 // Record source position of the IC call.
2644 SetSourcePosition(expr->position());
2645 CallFunctionStub stub(arg_count, CALL_AS_METHOD);
2646 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
2647 __ CallStub(&stub);
2648 RecordJSReturnSite(expr);
2649
2650 // Restore context register.
2651 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2652
2653 context()->DropAndPlug(1, eax);
2654 } 2614 }
2655 2615
2656 2616
2657 void FullCodeGenerator::EmitCallWithStub(Call* expr) { 2617 void FullCodeGenerator::EmitCall(Call* expr, CallIC::CallType call_type) {
2658 // Code common for calls using the call stub. 2618 // Load the arguments.
2659 ZoneList<Expression*>* args = expr->arguments(); 2619 ZoneList<Expression*>* args = expr->arguments();
2660 int arg_count = args->length(); 2620 int arg_count = args->length();
2661 { PreservePositionScope scope(masm()->positions_recorder()); 2621 { PreservePositionScope scope(masm()->positions_recorder());
2662 for (int i = 0; i < arg_count; i++) { 2622 for (int i = 0; i < arg_count; i++) {
2663 VisitForStackValue(args->at(i)); 2623 VisitForStackValue(args->at(i));
2664 } 2624 }
2665 } 2625 }
2666 // Record source position for debugger. 2626
2627 // Record source position of the IC call.
2667 SetSourcePosition(expr->position()); 2628 SetSourcePosition(expr->position());
2668 2629 Handle<Code> ic = CallIC::initialize_stub(
2630 isolate(), arg_count, call_type);
2669 Handle<Object> uninitialized = 2631 Handle<Object> uninitialized =
2670 TypeFeedbackInfo::UninitializedSentinel(isolate()); 2632 TypeFeedbackInfo::UninitializedSentinel(isolate());
2671 StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized); 2633 StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized);
2672 __ LoadHeapObject(ebx, FeedbackVector()); 2634 __ LoadHeapObject(ebx, FeedbackVector());
2673 __ mov(edx, Immediate(Smi::FromInt(expr->CallFeedbackSlot()))); 2635 __ mov(edx, Immediate(Smi::FromInt(expr->CallFeedbackSlot())));
2674
2675 // Record call targets in unoptimized code.
2676 CallFunctionStub stub(arg_count, RECORD_CALL_TARGET);
2677 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); 2636 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
2678 __ CallStub(&stub); 2637 // Don't assign a type feedback id to the IC, since type feedback is provided
2638 // by the vector above.
2639 CallIC(ic);
2679 2640
2680 RecordJSReturnSite(expr); 2641 RecordJSReturnSite(expr);
2642
2681 // Restore context register. 2643 // Restore context register.
2682 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2644 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2645
2683 context()->DropAndPlug(1, eax); 2646 context()->DropAndPlug(1, eax);
2684 } 2647 }
2685 2648
2686 2649
2687 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { 2650 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
2688 // Push copy of the first argument or undefined if it doesn't exist. 2651 // Push copy of the first argument or undefined if it doesn't exist.
2689 if (arg_count > 0) { 2652 if (arg_count > 0) {
2690 __ push(Operand(esp, arg_count * kPointerSize)); 2653 __ push(Operand(esp, arg_count * kPointerSize));
2691 } else { 2654 } else {
2692 __ push(Immediate(isolate()->factory()->undefined_value())); 2655 __ push(Immediate(isolate()->factory()->undefined_value()));
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2745 SetSourcePosition(expr->position()); 2708 SetSourcePosition(expr->position());
2746 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS); 2709 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS);
2747 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); 2710 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
2748 __ CallStub(&stub); 2711 __ CallStub(&stub);
2749 RecordJSReturnSite(expr); 2712 RecordJSReturnSite(expr);
2750 // Restore context register. 2713 // Restore context register.
2751 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2714 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2752 context()->DropAndPlug(1, eax); 2715 context()->DropAndPlug(1, eax);
2753 2716
2754 } else if (call_type == Call::GLOBAL_CALL) { 2717 } else if (call_type == Call::GLOBAL_CALL) {
2755 EmitCallWithIC(expr); 2718 EmitCallWithLoadIC(expr);
2756 2719
2757 } else if (call_type == Call::LOOKUP_SLOT_CALL) { 2720 } else if (call_type == Call::LOOKUP_SLOT_CALL) {
2758 // Call to a lookup slot (dynamically introduced variable). 2721 // Call to a lookup slot (dynamically introduced variable).
2759 VariableProxy* proxy = callee->AsVariableProxy(); 2722 VariableProxy* proxy = callee->AsVariableProxy();
2760 Label slow, done; 2723 Label slow, done;
2761 { PreservePositionScope scope(masm()->positions_recorder()); 2724 { PreservePositionScope scope(masm()->positions_recorder());
2762 // Generate code for loading from variables potentially shadowed by 2725 // Generate code for loading from variables potentially shadowed by
2763 // eval-introduced variables. 2726 // eval-introduced variables.
2764 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); 2727 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done);
2765 } 2728 }
(...skipping 15 matching lines...) Expand all
2781 // Push function. 2744 // Push function.
2782 __ push(eax); 2745 __ push(eax);
2783 // The receiver is implicitly the global receiver. Indicate this by 2746 // The receiver is implicitly the global receiver. Indicate this by
2784 // passing the hole to the call function stub. 2747 // passing the hole to the call function stub.
2785 __ push(Immediate(isolate()->factory()->undefined_value())); 2748 __ push(Immediate(isolate()->factory()->undefined_value()));
2786 __ bind(&call); 2749 __ bind(&call);
2787 } 2750 }
2788 2751
2789 // The receiver is either the global receiver or an object found by 2752 // The receiver is either the global receiver or an object found by
2790 // LoadContextSlot. 2753 // LoadContextSlot.
2791 EmitCallWithStub(expr); 2754 EmitCall(expr);
2792 2755
2793 } else if (call_type == Call::PROPERTY_CALL) { 2756 } else if (call_type == Call::PROPERTY_CALL) {
2794 Property* property = callee->AsProperty(); 2757 Property* property = callee->AsProperty();
2795 { PreservePositionScope scope(masm()->positions_recorder()); 2758 { PreservePositionScope scope(masm()->positions_recorder());
2796 VisitForStackValue(property->obj()); 2759 VisitForStackValue(property->obj());
2797 } 2760 }
2798 if (property->key()->IsPropertyName()) { 2761 if (property->key()->IsPropertyName()) {
2799 EmitCallWithIC(expr); 2762 EmitCallWithLoadIC(expr);
2800 } else { 2763 } else {
2801 EmitKeyedCallWithIC(expr, property->key()); 2764 EmitKeyedCallWithLoadIC(expr, property->key());
2802 } 2765 }
2803 2766
2804 } else { 2767 } else {
2805 ASSERT(call_type == Call::OTHER_CALL); 2768 ASSERT(call_type == Call::OTHER_CALL);
2806 // Call to an arbitrary expression not handled specially above. 2769 // Call to an arbitrary expression not handled specially above.
2807 { PreservePositionScope scope(masm()->positions_recorder()); 2770 { PreservePositionScope scope(masm()->positions_recorder());
2808 VisitForStackValue(callee); 2771 VisitForStackValue(callee);
2809 } 2772 }
2810 __ push(Immediate(isolate()->factory()->undefined_value())); 2773 __ push(Immediate(isolate()->factory()->undefined_value()));
2811 // Emit function call. 2774 // Emit function call.
2812 EmitCallWithStub(expr); 2775 EmitCall(expr);
2813 } 2776 }
2814 2777
2815 #ifdef DEBUG 2778 #ifdef DEBUG
2816 // RecordJSReturnSite should have been called. 2779 // RecordJSReturnSite should have been called.
2817 ASSERT(expr->return_is_recorded_); 2780 ASSERT(expr->return_is_recorded_);
2818 #endif 2781 #endif
2819 } 2782 }
2820 2783
2821 2784
2822 void FullCodeGenerator::VisitCallNew(CallNew* expr) { 2785 void FullCodeGenerator::VisitCallNew(CallNew* expr) {
(...skipping 2087 matching lines...) Expand 10 before | Expand all | Expand 10 after
4910 4873
4911 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), 4874 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(),
4912 Assembler::target_address_at(call_target_address)); 4875 Assembler::target_address_at(call_target_address));
4913 return OSR_AFTER_STACK_CHECK; 4876 return OSR_AFTER_STACK_CHECK;
4914 } 4877 }
4915 4878
4916 4879
4917 } } // namespace v8::internal 4880 } } // namespace v8::internal
4918 4881
4919 #endif // V8_TARGET_ARCH_IA32 4882 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698