| 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 #if V8_TARGET_ARCH_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
| 6 | 6 |
| 7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
| 8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
| 9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
| 10 #include "src/debug/debug.h" | 10 #include "src/debug/debug.h" |
| (...skipping 2030 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2041 // result = receiver[f](arg); | 2041 // result = receiver[f](arg); |
| 2042 __ bind(&l_call); | 2042 __ bind(&l_call); |
| 2043 __ mov(load_receiver, Operand(esp, kPointerSize)); | 2043 __ mov(load_receiver, Operand(esp, kPointerSize)); |
| 2044 __ mov(LoadDescriptor::SlotRegister(), | 2044 __ mov(LoadDescriptor::SlotRegister(), |
| 2045 Immediate(SmiFromSlot(expr->KeyedLoadFeedbackSlot()))); | 2045 Immediate(SmiFromSlot(expr->KeyedLoadFeedbackSlot()))); |
| 2046 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), SLOPPY).code(); | 2046 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), SLOPPY).code(); |
| 2047 CallIC(ic, TypeFeedbackId::None()); | 2047 CallIC(ic, TypeFeedbackId::None()); |
| 2048 __ mov(edi, eax); | 2048 __ mov(edi, eax); |
| 2049 __ mov(Operand(esp, 2 * kPointerSize), edi); | 2049 __ mov(Operand(esp, 2 * kPointerSize), edi); |
| 2050 SetCallPosition(expr, 1); | 2050 SetCallPosition(expr, 1); |
| 2051 CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD); | 2051 __ Set(eax, 1); |
| 2052 __ CallStub(&stub); | 2052 __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| 2053 | 2053 |
| 2054 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2054 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2055 __ Drop(1); // The function is still on the stack; drop it. | 2055 __ Drop(1); // The function is still on the stack; drop it. |
| 2056 | 2056 |
| 2057 // if (!result.done) goto l_try; | 2057 // if (!result.done) goto l_try; |
| 2058 __ bind(&l_loop); | 2058 __ bind(&l_loop); |
| 2059 __ push(eax); // save result | 2059 __ push(eax); // save result |
| 2060 __ Move(load_receiver, eax); // result | 2060 __ Move(load_receiver, eax); // result |
| 2061 __ mov(load_name, | 2061 __ mov(load_name, |
| 2062 isolate()->factory()->done_string()); // "done" | 2062 isolate()->factory()->done_string()); // "done" |
| (...skipping 648 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2711 TypeFeedbackId ast_id) { | 2711 TypeFeedbackId ast_id) { |
| 2712 ic_total_count_++; | 2712 ic_total_count_++; |
| 2713 __ call(code, RelocInfo::CODE_TARGET, ast_id); | 2713 __ call(code, RelocInfo::CODE_TARGET, ast_id); |
| 2714 } | 2714 } |
| 2715 | 2715 |
| 2716 | 2716 |
| 2717 // Code common for calls using the IC. | 2717 // Code common for calls using the IC. |
| 2718 void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) { | 2718 void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) { |
| 2719 Expression* callee = expr->expression(); | 2719 Expression* callee = expr->expression(); |
| 2720 | 2720 |
| 2721 CallICState::CallType call_type = | |
| 2722 callee->IsVariableProxy() ? CallICState::FUNCTION : CallICState::METHOD; | |
| 2723 // Get the target function. | 2721 // Get the target function. |
| 2724 if (call_type == CallICState::FUNCTION) { | 2722 if (callee->IsVariableProxy()) { |
| 2725 { StackValueContext context(this); | 2723 { StackValueContext context(this); |
| 2726 EmitVariableLoad(callee->AsVariableProxy()); | 2724 EmitVariableLoad(callee->AsVariableProxy()); |
| 2727 PrepareForBailout(callee, NO_REGISTERS); | 2725 PrepareForBailout(callee, NO_REGISTERS); |
| 2728 } | 2726 } |
| 2729 // Push undefined as receiver. This is patched in the method prologue if it | 2727 // Push undefined as receiver. This is patched in the method prologue if it |
| 2730 // is a sloppy mode method. | 2728 // is a sloppy mode method. |
| 2731 __ push(Immediate(isolate()->factory()->undefined_value())); | 2729 __ push(Immediate(isolate()->factory()->undefined_value())); |
| 2732 } else { | 2730 } else { |
| 2733 // Load the function from the receiver. | 2731 // Load the function from the receiver. |
| 2734 DCHECK(callee->IsProperty()); | 2732 DCHECK(callee->IsProperty()); |
| 2735 DCHECK(!callee->AsProperty()->IsSuperAccess()); | 2733 DCHECK(!callee->AsProperty()->IsSuperAccess()); |
| 2736 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0)); | 2734 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0)); |
| 2737 EmitNamedPropertyLoad(callee->AsProperty()); | 2735 EmitNamedPropertyLoad(callee->AsProperty()); |
| 2738 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2736 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
| 2739 // Push the target function under the receiver. | 2737 // Push the target function under the receiver. |
| 2740 __ push(Operand(esp, 0)); | 2738 __ push(Operand(esp, 0)); |
| 2741 __ mov(Operand(esp, kPointerSize), eax); | 2739 __ mov(Operand(esp, kPointerSize), eax); |
| 2742 } | 2740 } |
| 2743 | 2741 |
| 2744 EmitCall(expr, call_type); | 2742 EmitCall(expr); |
| 2745 } | 2743 } |
| 2746 | 2744 |
| 2747 | 2745 |
| 2748 void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) { | 2746 void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) { |
| 2749 SetExpressionPosition(expr); | 2747 SetExpressionPosition(expr); |
| 2750 Expression* callee = expr->expression(); | 2748 Expression* callee = expr->expression(); |
| 2751 DCHECK(callee->IsProperty()); | 2749 DCHECK(callee->IsProperty()); |
| 2752 Property* prop = callee->AsProperty(); | 2750 Property* prop = callee->AsProperty(); |
| 2753 DCHECK(prop->IsSuperAccess()); | 2751 DCHECK(prop->IsSuperAccess()); |
| 2754 | 2752 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2771 // - key | 2769 // - key |
| 2772 // - language_mode | 2770 // - language_mode |
| 2773 __ CallRuntime(Runtime::kLoadFromSuper, 4); | 2771 __ CallRuntime(Runtime::kLoadFromSuper, 4); |
| 2774 | 2772 |
| 2775 // Replace home_object with target function. | 2773 // Replace home_object with target function. |
| 2776 __ mov(Operand(esp, kPointerSize), eax); | 2774 __ mov(Operand(esp, kPointerSize), eax); |
| 2777 | 2775 |
| 2778 // Stack here: | 2776 // Stack here: |
| 2779 // - target function | 2777 // - target function |
| 2780 // - this (receiver) | 2778 // - this (receiver) |
| 2781 EmitCall(expr, CallICState::METHOD); | 2779 EmitCall(expr); |
| 2782 } | 2780 } |
| 2783 | 2781 |
| 2784 | 2782 |
| 2785 // Code common for calls using the IC. | 2783 // Code common for calls using the IC. |
| 2786 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, | 2784 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, |
| 2787 Expression* key) { | 2785 Expression* key) { |
| 2788 // Load the key. | 2786 // Load the key. |
| 2789 VisitForAccumulatorValue(key); | 2787 VisitForAccumulatorValue(key); |
| 2790 | 2788 |
| 2791 Expression* callee = expr->expression(); | 2789 Expression* callee = expr->expression(); |
| 2792 | 2790 |
| 2793 // Load the function from the receiver. | 2791 // Load the function from the receiver. |
| 2794 DCHECK(callee->IsProperty()); | 2792 DCHECK(callee->IsProperty()); |
| 2795 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0)); | 2793 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0)); |
| 2796 __ mov(LoadDescriptor::NameRegister(), eax); | 2794 __ mov(LoadDescriptor::NameRegister(), eax); |
| 2797 EmitKeyedPropertyLoad(callee->AsProperty()); | 2795 EmitKeyedPropertyLoad(callee->AsProperty()); |
| 2798 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2796 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
| 2799 | 2797 |
| 2800 // Push the target function under the receiver. | 2798 // Push the target function under the receiver. |
| 2801 __ push(Operand(esp, 0)); | 2799 __ push(Operand(esp, 0)); |
| 2802 __ mov(Operand(esp, kPointerSize), eax); | 2800 __ mov(Operand(esp, kPointerSize), eax); |
| 2803 | 2801 |
| 2804 EmitCall(expr, CallICState::METHOD); | 2802 EmitCall(expr); |
| 2805 } | 2803 } |
| 2806 | 2804 |
| 2807 | 2805 |
| 2808 void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) { | 2806 void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) { |
| 2809 Expression* callee = expr->expression(); | 2807 Expression* callee = expr->expression(); |
| 2810 DCHECK(callee->IsProperty()); | 2808 DCHECK(callee->IsProperty()); |
| 2811 Property* prop = callee->AsProperty(); | 2809 Property* prop = callee->AsProperty(); |
| 2812 DCHECK(prop->IsSuperAccess()); | 2810 DCHECK(prop->IsSuperAccess()); |
| 2813 | 2811 |
| 2814 SetExpressionPosition(prop); | 2812 SetExpressionPosition(prop); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2829 // - key | 2827 // - key |
| 2830 // - language_mode | 2828 // - language_mode |
| 2831 __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4); | 2829 __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4); |
| 2832 | 2830 |
| 2833 // Replace home_object with target function. | 2831 // Replace home_object with target function. |
| 2834 __ mov(Operand(esp, kPointerSize), eax); | 2832 __ mov(Operand(esp, kPointerSize), eax); |
| 2835 | 2833 |
| 2836 // Stack here: | 2834 // Stack here: |
| 2837 // - target function | 2835 // - target function |
| 2838 // - this (receiver) | 2836 // - this (receiver) |
| 2839 EmitCall(expr, CallICState::METHOD); | 2837 EmitCall(expr); |
| 2840 } | 2838 } |
| 2841 | 2839 |
| 2842 | 2840 |
| 2843 void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) { | 2841 void FullCodeGenerator::EmitCall(Call* expr) { |
| 2844 // Load the arguments. | 2842 // Load the arguments. |
| 2845 ZoneList<Expression*>* args = expr->arguments(); | 2843 ZoneList<Expression*>* args = expr->arguments(); |
| 2846 int arg_count = args->length(); | 2844 int arg_count = args->length(); |
| 2847 for (int i = 0; i < arg_count; i++) { | 2845 for (int i = 0; i < arg_count; i++) { |
| 2848 VisitForStackValue(args->at(i)); | 2846 VisitForStackValue(args->at(i)); |
| 2849 } | 2847 } |
| 2850 | 2848 |
| 2851 PrepareForBailoutForId(expr->CallId(), NO_REGISTERS); | 2849 PrepareForBailoutForId(expr->CallId(), NO_REGISTERS); |
| 2852 SetCallPosition(expr, arg_count); | 2850 SetCallPosition(expr, arg_count); |
| 2853 Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count, call_type).code(); | 2851 Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count).code(); |
| 2854 __ Move(edx, Immediate(SmiFromSlot(expr->CallFeedbackICSlot()))); | 2852 __ Move(edx, Immediate(SmiFromSlot(expr->CallFeedbackICSlot()))); |
| 2855 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); | 2853 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
| 2856 // Don't assign a type feedback id to the IC, since type feedback is provided | 2854 // Don't assign a type feedback id to the IC, since type feedback is provided |
| 2857 // by the vector above. | 2855 // by the vector above. |
| 2858 CallIC(ic); | 2856 CallIC(ic); |
| 2859 | 2857 |
| 2860 RecordJSReturnSite(expr); | 2858 RecordJSReturnSite(expr); |
| 2861 | 2859 |
| 2862 // Restore context register. | 2860 // Restore context register. |
| 2863 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2861 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2947 // resolve eval. | 2945 // resolve eval. |
| 2948 __ push(Operand(esp, (arg_count + 1) * kPointerSize)); | 2946 __ push(Operand(esp, (arg_count + 1) * kPointerSize)); |
| 2949 EmitResolvePossiblyDirectEval(arg_count); | 2947 EmitResolvePossiblyDirectEval(arg_count); |
| 2950 | 2948 |
| 2951 // Touch up the stack with the resolved function. | 2949 // Touch up the stack with the resolved function. |
| 2952 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax); | 2950 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax); |
| 2953 | 2951 |
| 2954 PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS); | 2952 PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS); |
| 2955 | 2953 |
| 2956 SetCallPosition(expr, arg_count); | 2954 SetCallPosition(expr, arg_count); |
| 2957 CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS); | |
| 2958 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); | 2955 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
| 2959 __ CallStub(&stub); | 2956 __ Set(eax, arg_count); |
| 2957 __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| 2960 RecordJSReturnSite(expr); | 2958 RecordJSReturnSite(expr); |
| 2961 // Restore context register. | 2959 // Restore context register. |
| 2962 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2960 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2963 context()->DropAndPlug(1, eax); | 2961 context()->DropAndPlug(1, eax); |
| 2964 } | 2962 } |
| 2965 | 2963 |
| 2966 | 2964 |
| 2967 void FullCodeGenerator::VisitCallNew(CallNew* expr) { | 2965 void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
| 2968 Comment cmnt(masm_, "[ CallNew"); | 2966 Comment cmnt(masm_, "[ CallNew"); |
| 2969 // According to ECMA-262, section 11.2.2, page 44, the function | 2967 // According to ECMA-262, section 11.2.2, page 44, the function |
| (...skipping 1233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4203 __ mov(eax, FieldOperand(eax, JSGlobalObject::kNativeContextOffset)); | 4201 __ mov(eax, FieldOperand(eax, JSGlobalObject::kNativeContextOffset)); |
| 4204 __ mov(eax, ContextOperand(eax, expr->context_index())); | 4202 __ mov(eax, ContextOperand(eax, expr->context_index())); |
| 4205 } | 4203 } |
| 4206 | 4204 |
| 4207 | 4205 |
| 4208 void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { | 4206 void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { |
| 4209 ZoneList<Expression*>* args = expr->arguments(); | 4207 ZoneList<Expression*>* args = expr->arguments(); |
| 4210 int arg_count = args->length(); | 4208 int arg_count = args->length(); |
| 4211 | 4209 |
| 4212 SetCallPosition(expr, arg_count); | 4210 SetCallPosition(expr, arg_count); |
| 4213 CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS); | |
| 4214 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); | 4211 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
| 4215 __ CallStub(&stub); | 4212 __ Set(eax, arg_count); |
| 4213 __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| 4216 } | 4214 } |
| 4217 | 4215 |
| 4218 | 4216 |
| 4219 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 4217 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
| 4220 ZoneList<Expression*>* args = expr->arguments(); | 4218 ZoneList<Expression*>* args = expr->arguments(); |
| 4221 int arg_count = args->length(); | 4219 int arg_count = args->length(); |
| 4222 | 4220 |
| 4223 if (expr->is_jsruntime()) { | 4221 if (expr->is_jsruntime()) { |
| 4224 Comment cmnt(masm_, "[ CallRuntime"); | 4222 Comment cmnt(masm_, "[ CallRuntime"); |
| 4225 EmitLoadJSRuntimeFunction(expr); | 4223 EmitLoadJSRuntimeFunction(expr); |
| (...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5014 Assembler::target_address_at(call_target_address, | 5012 Assembler::target_address_at(call_target_address, |
| 5015 unoptimized_code)); | 5013 unoptimized_code)); |
| 5016 return OSR_AFTER_STACK_CHECK; | 5014 return OSR_AFTER_STACK_CHECK; |
| 5017 } | 5015 } |
| 5018 | 5016 |
| 5019 | 5017 |
| 5020 } // namespace internal | 5018 } // namespace internal |
| 5021 } // namespace v8 | 5019 } // namespace v8 |
| 5022 | 5020 |
| 5023 #endif // V8_TARGET_ARCH_IA32 | 5021 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |