| 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 |