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

Side by Side Diff: src/x64/codegen-x64.cc

Issue 245042: Remove CallEval as a subclass of the Call AST node type. We were not... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 2 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/variables.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 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 2686 matching lines...) Expand 10 before | Expand all | Expand 10 after
2697 2697
2698 // ------------------------------------------------------------------------ 2698 // ------------------------------------------------------------------------
2699 // Fast-case: Use inline caching. 2699 // Fast-case: Use inline caching.
2700 // --- 2700 // ---
2701 // According to ECMA-262, section 11.2.3, page 44, the function to call 2701 // According to ECMA-262, section 11.2.3, page 44, the function to call
2702 // must be resolved after the arguments have been evaluated. The IC code 2702 // must be resolved after the arguments have been evaluated. The IC code
2703 // automatically handles this by loading the arguments before the function 2703 // automatically handles this by loading the arguments before the function
2704 // is resolved in cache misses (this also holds for megamorphic calls). 2704 // is resolved in cache misses (this also holds for megamorphic calls).
2705 // ------------------------------------------------------------------------ 2705 // ------------------------------------------------------------------------
2706 2706
2707 if (var != NULL && !var->is_this() && var->is_global()) { 2707 if (var != NULL && var->is_possibly_eval()) {
2708 // ----------------------------------
2709 // JavaScript example: 'eval(arg)' // eval is not known to be shadowed
2710 // ----------------------------------
2711
2712 // In a call to eval, we first call %ResolvePossiblyDirectEval to
2713 // resolve the function we need to call and the receiver of the
2714 // call. Then we call the resolved function using the given
2715 // arguments.
2716
2717 // Prepare the stack for the call to the resolved function.
2718 Load(function);
2719
2720 // Allocate a frame slot for the receiver.
2721 frame_->Push(Factory::undefined_value());
2722 int arg_count = args->length();
2723 for (int i = 0; i < arg_count; i++) {
2724 Load(args->at(i));
2725 }
2726
2727 // Prepare the stack for the call to ResolvePossiblyDirectEval.
2728 frame_->PushElementAt(arg_count + 1);
2729 if (arg_count > 0) {
2730 frame_->PushElementAt(arg_count);
2731 } else {
2732 frame_->Push(Factory::undefined_value());
2733 }
2734
2735 // Resolve the call.
2736 Result result =
2737 frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 2);
2738
2739 // Touch up the stack with the right values for the function and the
2740 // receiver. Use a scratch register to avoid destroying the result.
2741 Result scratch = allocator_->Allocate();
2742 ASSERT(scratch.is_valid());
2743 __ movq(scratch.reg(),
2744 FieldOperand(result.reg(), FixedArray::OffsetOfElementAt(0)));
2745 frame_->SetElementAt(arg_count + 1, &scratch);
2746
2747 // We can reuse the result register now.
2748 frame_->Spill(result.reg());
2749 __ movq(result.reg(),
2750 FieldOperand(result.reg(), FixedArray::OffsetOfElementAt(1)));
2751 frame_->SetElementAt(arg_count, &result);
2752
2753 // Call the function.
2754 CodeForSourcePosition(node->position());
2755 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
2756 CallFunctionStub call_function(arg_count, in_loop);
2757 result = frame_->CallStub(&call_function, arg_count + 1);
2758
2759 // Restore the context and overwrite the function on the stack with
2760 // the result.
2761 frame_->RestoreContextRegister();
2762 frame_->SetElementAt(0, &result);
2763
2764 } else if (var != NULL && !var->is_this() && var->is_global()) {
2708 // ---------------------------------- 2765 // ----------------------------------
2709 // JavaScript example: 'foo(1, 2, 3)' // foo is global 2766 // JavaScript example: 'foo(1, 2, 3)' // foo is global
2710 // ---------------------------------- 2767 // ----------------------------------
2711 2768
2712 // Push the name of the function and the receiver onto the stack. 2769 // Push the name of the function and the receiver onto the stack.
2713 frame_->Push(var->name()); 2770 frame_->Push(var->name());
2714 2771
2715 // Pass the global object as the receiver and let the IC stub 2772 // Pass the global object as the receiver and let the IC stub
2716 // patch the stack to use the global proxy as 'this' in the 2773 // patch the stack to use the global proxy as 'this' in the
2717 // invoked function. 2774 // invoked function.
2718 LoadGlobal(); 2775 LoadGlobal();
2719 2776
2720 // Load the arguments. 2777 // Load the arguments.
2721 int arg_count = args->length(); 2778 int arg_count = args->length();
2722 for (int i = 0; i < arg_count; i++) { 2779 for (int i = 0; i < arg_count; i++) {
2723 Load(args->at(i)); 2780 Load(args->at(i));
2724 } 2781 }
2725 2782
2726 // Call the IC initialization code. 2783 // Call the IC initialization code.
2727 CodeForSourcePosition(node->position()); 2784 CodeForSourcePosition(node->position());
2728 Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT, 2785 Result result = frame_->CallCallIC(RelocInfo::CODE_TARGET_CONTEXT,
2729 arg_count, 2786 arg_count,
2730 loop_nesting()); 2787 loop_nesting());
2731 frame_->RestoreContextRegister(); 2788 frame_->RestoreContextRegister();
2732 // Replace the function on the stack with the result. 2789 // Replace the function on the stack with the result.
2733 frame_->SetElementAt(0, &result); 2790 frame_->SetElementAt(0, &result);
2791
2734 } else if (var != NULL && var->slot() != NULL && 2792 } else if (var != NULL && var->slot() != NULL &&
2735 var->slot()->type() == Slot::LOOKUP) { 2793 var->slot()->type() == Slot::LOOKUP) {
2736 // ---------------------------------- 2794 // ----------------------------------
2737 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj 2795 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj
2738 // ---------------------------------- 2796 // ----------------------------------
2739 2797
2740 // Load the function from the context. Sync the frame so we can 2798 // Load the function from the context. Sync the frame so we can
2741 // push the arguments directly into place. 2799 // push the arguments directly into place.
2742 frame_->SyncRange(0, frame_->element_count() - 1); 2800 frame_->SyncRange(0, frame_->element_count() - 1);
2743 frame_->EmitPush(rsi); 2801 frame_->EmitPush(rsi);
2744 frame_->EmitPush(var->name()); 2802 frame_->EmitPush(var->name());
2745 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); 2803 frame_->CallRuntime(Runtime::kLoadContextSlot, 2);
2746 // The runtime call returns a pair of values in rax and rdx. The 2804 // The runtime call returns a pair of values in rax and rdx. The
2747 // looked-up function is in rax and the receiver is in rdx. These 2805 // looked-up function is in rax and the receiver is in rdx. These
2748 // register references are not ref counted here. We spill them 2806 // register references are not ref counted here. We spill them
2749 // eagerly since they are arguments to an inevitable call (and are 2807 // eagerly since they are arguments to an inevitable call (and are
2750 // not sharable by the arguments). 2808 // not sharable by the arguments).
2751 ASSERT(!allocator()->is_used(rax)); 2809 ASSERT(!allocator()->is_used(rax));
2752 frame_->EmitPush(rax); 2810 frame_->EmitPush(rax);
2753 2811
2754 // Load the receiver. 2812 // Load the receiver.
2755 ASSERT(!allocator()->is_used(rdx)); 2813 ASSERT(!allocator()->is_used(rdx));
2756 frame_->EmitPush(rdx); 2814 frame_->EmitPush(rdx);
2757 2815
2758 // Call the function. 2816 // Call the function.
2759 CallWithArguments(args, node->position()); 2817 CallWithArguments(args, node->position());
2818
2760 } else if (property != NULL) { 2819 } else if (property != NULL) {
2761 // Check if the key is a literal string. 2820 // Check if the key is a literal string.
2762 Literal* literal = property->key()->AsLiteral(); 2821 Literal* literal = property->key()->AsLiteral();
2763 2822
2764 if (literal != NULL && literal->handle()->IsSymbol()) { 2823 if (literal != NULL && literal->handle()->IsSymbol()) {
2765 // ------------------------------------------------------------------ 2824 // ------------------------------------------------------------------
2766 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' 2825 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)'
2767 // ------------------------------------------------------------------ 2826 // ------------------------------------------------------------------
2768 2827
2769 Handle<String> name = Handle<String>::cast(literal->handle()); 2828 Handle<String> name = Handle<String>::cast(literal->handle());
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
2815 // Use global object as receiver. 2874 // Use global object as receiver.
2816 LoadGlobalReceiver(); 2875 LoadGlobalReceiver();
2817 } else { 2876 } else {
2818 // The reference's size is non-negative. 2877 // The reference's size is non-negative.
2819 frame_->PushElementAt(ref.size()); 2878 frame_->PushElementAt(ref.size());
2820 } 2879 }
2821 2880
2822 // Call the function. 2881 // Call the function.
2823 CallWithArguments(args, node->position()); 2882 CallWithArguments(args, node->position());
2824 } 2883 }
2884
2825 } else { 2885 } else {
2826 // ---------------------------------- 2886 // ----------------------------------
2827 // JavaScript example: 'foo(1, 2, 3)' // foo is not global 2887 // JavaScript example: 'foo(1, 2, 3)' // foo is not global
2828 // ---------------------------------- 2888 // ----------------------------------
2829 2889
2830 // Load the function. 2890 // Load the function.
2831 Load(function); 2891 Load(function);
2832 2892
2833 // Pass the global proxy as the receiver. 2893 // Pass the global proxy as the receiver.
2834 LoadGlobalReceiver(); 2894 LoadGlobalReceiver();
2835 2895
2836 // Call the function. 2896 // Call the function.
2837 CallWithArguments(args, node->position()); 2897 CallWithArguments(args, node->position());
2838 } 2898 }
2839 } 2899 }
2840 2900
2841 2901
2842 void CodeGenerator::VisitCallEval(CallEval* node) {
2843 Comment cmnt(masm_, "[ CallEval");
2844
2845 // In a call to eval, we first call %ResolvePossiblyDirectEval to resolve
2846 // the function we need to call and the receiver of the call.
2847 // Then we call the resolved function using the given arguments.
2848
2849 ZoneList<Expression*>* args = node->arguments();
2850 Expression* function = node->expression();
2851
2852 // Prepare the stack for the call to the resolved function.
2853 Load(function);
2854
2855 // Allocate a frame slot for the receiver.
2856 frame_->Push(Factory::undefined_value());
2857 int arg_count = args->length();
2858 for (int i = 0; i < arg_count; i++) {
2859 Load(args->at(i));
2860 }
2861
2862 // Prepare the stack for the call to ResolvePossiblyDirectEval.
2863 frame_->PushElementAt(arg_count + 1);
2864 if (arg_count > 0) {
2865 frame_->PushElementAt(arg_count);
2866 } else {
2867 frame_->Push(Factory::undefined_value());
2868 }
2869
2870 // Resolve the call.
2871 Result result =
2872 frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 2);
2873
2874 // Touch up the stack with the right values for the function and the
2875 // receiver. Use a scratch register to avoid destroying the result.
2876 Result scratch = allocator_->Allocate();
2877 ASSERT(scratch.is_valid());
2878 __ movq(scratch.reg(),
2879 FieldOperand(result.reg(), FixedArray::OffsetOfElementAt(0)));
2880 frame_->SetElementAt(arg_count + 1, &scratch);
2881
2882 // We can reuse the result register now.
2883 frame_->Spill(result.reg());
2884 __ movq(result.reg(),
2885 FieldOperand(result.reg(), FixedArray::OffsetOfElementAt(1)));
2886 frame_->SetElementAt(arg_count, &result);
2887
2888 // Call the function.
2889 CodeForSourcePosition(node->position());
2890 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
2891 CallFunctionStub call_function(arg_count, in_loop);
2892 result = frame_->CallStub(&call_function, arg_count + 1);
2893
2894 // Restore the context and overwrite the function on the stack with
2895 // the result.
2896 frame_->RestoreContextRegister();
2897 frame_->SetElementAt(0, &result);
2898 }
2899
2900
2901 void CodeGenerator::VisitCallNew(CallNew* node) { 2902 void CodeGenerator::VisitCallNew(CallNew* node) {
2902 Comment cmnt(masm_, "[ CallNew"); 2903 Comment cmnt(masm_, "[ CallNew");
2903 2904
2904 // According to ECMA-262, section 11.2.2, page 44, the function 2905 // According to ECMA-262, section 11.2.2, page 44, the function
2905 // expression in new calls must be evaluated before the 2906 // expression in new calls must be evaluated before the
2906 // arguments. This is different from ordinary calls, where the 2907 // arguments. This is different from ordinary calls, where the
2907 // actual function to call is resolved after the arguments have been 2908 // actual function to call is resolved after the arguments have been
2908 // evaluated. 2909 // evaluated.
2909 2910
2910 // Compute function to call and use the global object as the 2911 // Compute function to call and use the global object as the
(...skipping 4763 matching lines...) Expand 10 before | Expand all | Expand 10 after
7674 int CompareStub::MinorKey() { 7675 int CompareStub::MinorKey() {
7675 // Encode the two parameters in a unique 16 bit value. 7676 // Encode the two parameters in a unique 16 bit value.
7676 ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); 7677 ASSERT(static_cast<unsigned>(cc_) < (1 << 15));
7677 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); 7678 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0);
7678 } 7679 }
7679 7680
7680 7681
7681 #undef __ 7682 #undef __
7682 7683
7683 } } // namespace v8::internal 7684 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/variables.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698