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_X87 | 5 #if V8_TARGET_ARCH_X87 |
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 1711 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1722 __ mov(FieldOperand(ebx, offset), result_register()); | 1722 __ mov(FieldOperand(ebx, offset), result_register()); |
1723 // Update the write barrier for the array store. | 1723 // Update the write barrier for the array store. |
1724 __ RecordWriteField(ebx, offset, result_register(), ecx, kDontSaveFPRegs, | 1724 __ RecordWriteField(ebx, offset, result_register(), ecx, kDontSaveFPRegs, |
1725 EMIT_REMEMBERED_SET, INLINE_SMI_CHECK); | 1725 EMIT_REMEMBERED_SET, INLINE_SMI_CHECK); |
1726 } else { | 1726 } else { |
1727 // Store the subexpression value in the array's elements. | 1727 // Store the subexpression value in the array's elements. |
1728 __ mov(ecx, Immediate(Smi::FromInt(array_index))); | 1728 __ mov(ecx, Immediate(Smi::FromInt(array_index))); |
1729 StoreArrayLiteralElementStub stub(isolate()); | 1729 StoreArrayLiteralElementStub stub(isolate()); |
1730 __ CallStub(&stub); | 1730 __ CallStub(&stub); |
1731 } | 1731 } |
1732 | |
1733 PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS); | 1732 PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS); |
1734 } | 1733 } |
1735 | 1734 |
1736 // In case the array literal contains spread expressions it has two parts. The | 1735 // In case the array literal contains spread expressions it has two parts. The |
1737 // first part is the "static" array which has a literal index is handled | 1736 // first part is the "static" array which has a literal index is handled |
1738 // above. The second part is the part after the first spread expression | 1737 // above. The second part is the part after the first spread expression |
1739 // (inclusive) and these elements gets appended to the array. Note that the | 1738 // (inclusive) and these elements gets appended to the array. Note that the |
1740 // number elements an iterable produces is unknown ahead of time. | 1739 // number elements an iterable produces is unknown ahead of time. |
1741 if (array_index < length && result_saved) { | 1740 if (array_index < length && result_saved) { |
1742 __ Drop(1); // literal index | 1741 __ Drop(1); // literal index |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2034 // result = receiver[f](arg); | 2033 // result = receiver[f](arg); |
2035 __ bind(&l_call); | 2034 __ bind(&l_call); |
2036 __ mov(load_receiver, Operand(esp, kPointerSize)); | 2035 __ mov(load_receiver, Operand(esp, kPointerSize)); |
2037 __ mov(LoadDescriptor::SlotRegister(), | 2036 __ mov(LoadDescriptor::SlotRegister(), |
2038 Immediate(SmiFromSlot(expr->KeyedLoadFeedbackSlot()))); | 2037 Immediate(SmiFromSlot(expr->KeyedLoadFeedbackSlot()))); |
2039 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), SLOPPY).code(); | 2038 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), SLOPPY).code(); |
2040 CallIC(ic, TypeFeedbackId::None()); | 2039 CallIC(ic, TypeFeedbackId::None()); |
2041 __ mov(edi, eax); | 2040 __ mov(edi, eax); |
2042 __ mov(Operand(esp, 2 * kPointerSize), edi); | 2041 __ mov(Operand(esp, 2 * kPointerSize), edi); |
2043 SetCallPosition(expr, 1); | 2042 SetCallPosition(expr, 1); |
2044 CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD); | 2043 __ Set(eax, 1); |
2045 __ CallStub(&stub); | 2044 __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
2046 | 2045 |
2047 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2046 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
2048 __ Drop(1); // The function is still on the stack; drop it. | 2047 __ Drop(1); // The function is still on the stack; drop it. |
2049 | 2048 |
2050 // if (!result.done) goto l_try; | 2049 // if (!result.done) goto l_try; |
2051 __ bind(&l_loop); | 2050 __ bind(&l_loop); |
2052 __ push(eax); // save result | 2051 __ push(eax); // save result |
2053 __ Move(load_receiver, eax); // result | 2052 __ Move(load_receiver, eax); // result |
2054 __ mov(load_name, | 2053 __ mov(load_name, |
2055 isolate()->factory()->done_string()); // "done" | 2054 isolate()->factory()->done_string()); // "done" |
(...skipping 648 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2704 TypeFeedbackId ast_id) { | 2703 TypeFeedbackId ast_id) { |
2705 ic_total_count_++; | 2704 ic_total_count_++; |
2706 __ call(code, RelocInfo::CODE_TARGET, ast_id); | 2705 __ call(code, RelocInfo::CODE_TARGET, ast_id); |
2707 } | 2706 } |
2708 | 2707 |
2709 | 2708 |
2710 // Code common for calls using the IC. | 2709 // Code common for calls using the IC. |
2711 void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) { | 2710 void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) { |
2712 Expression* callee = expr->expression(); | 2711 Expression* callee = expr->expression(); |
2713 | 2712 |
2714 CallICState::CallType call_type = | |
2715 callee->IsVariableProxy() ? CallICState::FUNCTION : CallICState::METHOD; | |
2716 // Get the target function. | 2713 // Get the target function. |
2717 if (call_type == CallICState::FUNCTION) { | 2714 if (callee->IsVariableProxy()) { |
2718 { StackValueContext context(this); | 2715 { StackValueContext context(this); |
2719 EmitVariableLoad(callee->AsVariableProxy()); | 2716 EmitVariableLoad(callee->AsVariableProxy()); |
2720 PrepareForBailout(callee, NO_REGISTERS); | 2717 PrepareForBailout(callee, NO_REGISTERS); |
2721 } | 2718 } |
2722 // Push undefined as receiver. This is patched in the method prologue if it | 2719 // Push undefined as receiver. This is patched in the method prologue if it |
2723 // is a sloppy mode method. | 2720 // is a sloppy mode method. |
2724 __ push(Immediate(isolate()->factory()->undefined_value())); | 2721 __ push(Immediate(isolate()->factory()->undefined_value())); |
2725 } else { | 2722 } else { |
2726 // Load the function from the receiver. | 2723 // Load the function from the receiver. |
2727 DCHECK(callee->IsProperty()); | 2724 DCHECK(callee->IsProperty()); |
2728 DCHECK(!callee->AsProperty()->IsSuperAccess()); | 2725 DCHECK(!callee->AsProperty()->IsSuperAccess()); |
2729 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0)); | 2726 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0)); |
2730 EmitNamedPropertyLoad(callee->AsProperty()); | 2727 EmitNamedPropertyLoad(callee->AsProperty()); |
2731 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2728 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
2732 // Push the target function under the receiver. | 2729 // Push the target function under the receiver. |
2733 __ push(Operand(esp, 0)); | 2730 __ push(Operand(esp, 0)); |
2734 __ mov(Operand(esp, kPointerSize), eax); | 2731 __ mov(Operand(esp, kPointerSize), eax); |
2735 } | 2732 } |
2736 | 2733 |
2737 EmitCall(expr, call_type); | 2734 EmitCall(expr); |
2738 } | 2735 } |
2739 | 2736 |
2740 | 2737 |
2741 void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) { | 2738 void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) { |
2742 SetExpressionPosition(expr); | 2739 SetExpressionPosition(expr); |
2743 Expression* callee = expr->expression(); | 2740 Expression* callee = expr->expression(); |
2744 DCHECK(callee->IsProperty()); | 2741 DCHECK(callee->IsProperty()); |
2745 Property* prop = callee->AsProperty(); | 2742 Property* prop = callee->AsProperty(); |
2746 DCHECK(prop->IsSuperAccess()); | 2743 DCHECK(prop->IsSuperAccess()); |
2747 | 2744 |
(...skipping 16 matching lines...) Expand all Loading... |
2764 // - key | 2761 // - key |
2765 // - language_mode | 2762 // - language_mode |
2766 __ CallRuntime(Runtime::kLoadFromSuper, 4); | 2763 __ CallRuntime(Runtime::kLoadFromSuper, 4); |
2767 | 2764 |
2768 // Replace home_object with target function. | 2765 // Replace home_object with target function. |
2769 __ mov(Operand(esp, kPointerSize), eax); | 2766 __ mov(Operand(esp, kPointerSize), eax); |
2770 | 2767 |
2771 // Stack here: | 2768 // Stack here: |
2772 // - target function | 2769 // - target function |
2773 // - this (receiver) | 2770 // - this (receiver) |
2774 EmitCall(expr, CallICState::METHOD); | 2771 EmitCall(expr); |
2775 } | 2772 } |
2776 | 2773 |
2777 | 2774 |
2778 // Code common for calls using the IC. | 2775 // Code common for calls using the IC. |
2779 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, | 2776 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, |
2780 Expression* key) { | 2777 Expression* key) { |
2781 // Load the key. | 2778 // Load the key. |
2782 VisitForAccumulatorValue(key); | 2779 VisitForAccumulatorValue(key); |
2783 | 2780 |
2784 Expression* callee = expr->expression(); | 2781 Expression* callee = expr->expression(); |
2785 | 2782 |
2786 // Load the function from the receiver. | 2783 // Load the function from the receiver. |
2787 DCHECK(callee->IsProperty()); | 2784 DCHECK(callee->IsProperty()); |
2788 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0)); | 2785 __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0)); |
2789 __ mov(LoadDescriptor::NameRegister(), eax); | 2786 __ mov(LoadDescriptor::NameRegister(), eax); |
2790 EmitKeyedPropertyLoad(callee->AsProperty()); | 2787 EmitKeyedPropertyLoad(callee->AsProperty()); |
2791 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2788 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
2792 | 2789 |
2793 // Push the target function under the receiver. | 2790 // Push the target function under the receiver. |
2794 __ push(Operand(esp, 0)); | 2791 __ push(Operand(esp, 0)); |
2795 __ mov(Operand(esp, kPointerSize), eax); | 2792 __ mov(Operand(esp, kPointerSize), eax); |
2796 | 2793 |
2797 EmitCall(expr, CallICState::METHOD); | 2794 EmitCall(expr); |
2798 } | 2795 } |
2799 | 2796 |
2800 | 2797 |
2801 void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) { | 2798 void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) { |
2802 Expression* callee = expr->expression(); | 2799 Expression* callee = expr->expression(); |
2803 DCHECK(callee->IsProperty()); | 2800 DCHECK(callee->IsProperty()); |
2804 Property* prop = callee->AsProperty(); | 2801 Property* prop = callee->AsProperty(); |
2805 DCHECK(prop->IsSuperAccess()); | 2802 DCHECK(prop->IsSuperAccess()); |
2806 | 2803 |
2807 SetExpressionPosition(prop); | 2804 SetExpressionPosition(prop); |
(...skipping 14 matching lines...) Expand all Loading... |
2822 // - key | 2819 // - key |
2823 // - language_mode | 2820 // - language_mode |
2824 __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4); | 2821 __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4); |
2825 | 2822 |
2826 // Replace home_object with target function. | 2823 // Replace home_object with target function. |
2827 __ mov(Operand(esp, kPointerSize), eax); | 2824 __ mov(Operand(esp, kPointerSize), eax); |
2828 | 2825 |
2829 // Stack here: | 2826 // Stack here: |
2830 // - target function | 2827 // - target function |
2831 // - this (receiver) | 2828 // - this (receiver) |
2832 EmitCall(expr, CallICState::METHOD); | 2829 EmitCall(expr); |
2833 } | 2830 } |
2834 | 2831 |
2835 | 2832 |
2836 void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) { | 2833 void FullCodeGenerator::EmitCall(Call* expr) { |
2837 // Load the arguments. | 2834 // Load the arguments. |
2838 ZoneList<Expression*>* args = expr->arguments(); | 2835 ZoneList<Expression*>* args = expr->arguments(); |
2839 int arg_count = args->length(); | 2836 int arg_count = args->length(); |
2840 for (int i = 0; i < arg_count; i++) { | 2837 for (int i = 0; i < arg_count; i++) { |
2841 VisitForStackValue(args->at(i)); | 2838 VisitForStackValue(args->at(i)); |
2842 } | 2839 } |
2843 | 2840 |
2844 PrepareForBailoutForId(expr->CallId(), NO_REGISTERS); | 2841 PrepareForBailoutForId(expr->CallId(), NO_REGISTERS); |
2845 SetCallPosition(expr, arg_count); | 2842 SetCallPosition(expr, arg_count); |
2846 Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count, call_type).code(); | 2843 Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count).code(); |
2847 __ Move(edx, Immediate(SmiFromSlot(expr->CallFeedbackICSlot()))); | 2844 __ Move(edx, Immediate(SmiFromSlot(expr->CallFeedbackICSlot()))); |
2848 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); | 2845 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
2849 // Don't assign a type feedback id to the IC, since type feedback is provided | 2846 // Don't assign a type feedback id to the IC, since type feedback is provided |
2850 // by the vector above. | 2847 // by the vector above. |
2851 CallIC(ic); | 2848 CallIC(ic); |
2852 | 2849 |
2853 RecordJSReturnSite(expr); | 2850 RecordJSReturnSite(expr); |
2854 | 2851 |
2855 // Restore context register. | 2852 // Restore context register. |
2856 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2853 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2940 // resolve eval. | 2937 // resolve eval. |
2941 __ push(Operand(esp, (arg_count + 1) * kPointerSize)); | 2938 __ push(Operand(esp, (arg_count + 1) * kPointerSize)); |
2942 EmitResolvePossiblyDirectEval(arg_count); | 2939 EmitResolvePossiblyDirectEval(arg_count); |
2943 | 2940 |
2944 // Touch up the stack with the resolved function. | 2941 // Touch up the stack with the resolved function. |
2945 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax); | 2942 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax); |
2946 | 2943 |
2947 PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS); | 2944 PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS); |
2948 | 2945 |
2949 SetCallPosition(expr, arg_count); | 2946 SetCallPosition(expr, arg_count); |
2950 CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS); | |
2951 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); | 2947 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
2952 __ CallStub(&stub); | 2948 __ Set(eax, arg_count); |
| 2949 __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
2953 RecordJSReturnSite(expr); | 2950 RecordJSReturnSite(expr); |
2954 // Restore context register. | 2951 // Restore context register. |
2955 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2952 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
2956 context()->DropAndPlug(1, eax); | 2953 context()->DropAndPlug(1, eax); |
2957 } | 2954 } |
2958 | 2955 |
2959 | 2956 |
2960 void FullCodeGenerator::VisitCallNew(CallNew* expr) { | 2957 void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
2961 Comment cmnt(masm_, "[ CallNew"); | 2958 Comment cmnt(masm_, "[ CallNew"); |
2962 // According to ECMA-262, section 11.2.2, page 44, the function | 2959 // According to ECMA-262, section 11.2.2, page 44, the function |
(...skipping 1187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4150 __ mov(eax, FieldOperand(eax, JSGlobalObject::kNativeContextOffset)); | 4147 __ mov(eax, FieldOperand(eax, JSGlobalObject::kNativeContextOffset)); |
4151 __ mov(eax, ContextOperand(eax, expr->context_index())); | 4148 __ mov(eax, ContextOperand(eax, expr->context_index())); |
4152 } | 4149 } |
4153 | 4150 |
4154 | 4151 |
4155 void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { | 4152 void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { |
4156 ZoneList<Expression*>* args = expr->arguments(); | 4153 ZoneList<Expression*>* args = expr->arguments(); |
4157 int arg_count = args->length(); | 4154 int arg_count = args->length(); |
4158 | 4155 |
4159 SetCallPosition(expr, arg_count); | 4156 SetCallPosition(expr, arg_count); |
4160 CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS); | |
4161 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); | 4157 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
4162 __ CallStub(&stub); | 4158 __ Set(eax, arg_count); |
| 4159 __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
4163 } | 4160 } |
4164 | 4161 |
4165 | 4162 |
4166 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 4163 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
4167 ZoneList<Expression*>* args = expr->arguments(); | 4164 ZoneList<Expression*>* args = expr->arguments(); |
4168 int arg_count = args->length(); | 4165 int arg_count = args->length(); |
4169 | 4166 |
4170 if (expr->is_jsruntime()) { | 4167 if (expr->is_jsruntime()) { |
4171 Comment cmnt(masm_, "[ CallRuntime"); | 4168 Comment cmnt(masm_, "[ CallRuntime"); |
4172 EmitLoadJSRuntimeFunction(expr); | 4169 EmitLoadJSRuntimeFunction(expr); |
(...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4961 Assembler::target_address_at(call_target_address, | 4958 Assembler::target_address_at(call_target_address, |
4962 unoptimized_code)); | 4959 unoptimized_code)); |
4963 return OSR_AFTER_STACK_CHECK; | 4960 return OSR_AFTER_STACK_CHECK; |
4964 } | 4961 } |
4965 | 4962 |
4966 | 4963 |
4967 } // namespace internal | 4964 } // namespace internal |
4968 } // namespace v8 | 4965 } // namespace v8 |
4969 | 4966 |
4970 #endif // V8_TARGET_ARCH_X87 | 4967 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |