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/crankshaft/x87/lithium-codegen-x87.h" | 7 #include "src/crankshaft/x87/lithium-codegen-x87.h" |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 bool LCodeGen::GenerateCode() { | 50 bool LCodeGen::GenerateCode() { |
51 LPhase phase("Z_Code generation", chunk()); | 51 LPhase phase("Z_Code generation", chunk()); |
52 DCHECK(is_unused()); | 52 DCHECK(is_unused()); |
53 status_ = GENERATING; | 53 status_ = GENERATING; |
54 | 54 |
55 // Open a frame scope to indicate that there is a frame on the stack. The | 55 // Open a frame scope to indicate that there is a frame on the stack. The |
56 // MANUAL indicates that the scope shouldn't actually generate code to set up | 56 // MANUAL indicates that the scope shouldn't actually generate code to set up |
57 // the frame (that is done in GeneratePrologue). | 57 // the frame (that is done in GeneratePrologue). |
58 FrameScope frame_scope(masm_, StackFrame::MANUAL); | 58 FrameScope frame_scope(masm_, StackFrame::MANUAL); |
59 | 59 |
60 support_aligned_spilled_doubles_ = info()->IsOptimizing(); | |
61 | |
62 dynamic_frame_alignment_ = info()->IsOptimizing() && | |
63 ((chunk()->num_double_slots() > 2 && | |
64 !chunk()->graph()->is_recursive()) || | |
65 !info()->osr_ast_id().IsNone()); | |
66 | |
67 return GeneratePrologue() && | 60 return GeneratePrologue() && |
68 GenerateBody() && | 61 GenerateBody() && |
69 GenerateDeferredCode() && | 62 GenerateDeferredCode() && |
70 GenerateJumpTable() && | 63 GenerateJumpTable() && |
71 GenerateSafepointTable(); | 64 GenerateSafepointTable(); |
72 } | 65 } |
73 | 66 |
74 | 67 |
75 void LCodeGen::FinishCode(Handle<Code> code) { | 68 void LCodeGen::FinishCode(Handle<Code> code) { |
76 DCHECK(is_done()); | 69 DCHECK(is_done()); |
(...skipping 14 matching lines...) Expand all Loading... |
91 } | 84 } |
92 } | 85 } |
93 #endif | 86 #endif |
94 | 87 |
95 | 88 |
96 bool LCodeGen::GeneratePrologue() { | 89 bool LCodeGen::GeneratePrologue() { |
97 DCHECK(is_generating()); | 90 DCHECK(is_generating()); |
98 | 91 |
99 if (info()->IsOptimizing()) { | 92 if (info()->IsOptimizing()) { |
100 ProfileEntryHookStub::MaybeCallEntryHook(masm_); | 93 ProfileEntryHookStub::MaybeCallEntryHook(masm_); |
101 | |
102 if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) { | |
103 // Move state of dynamic frame alignment into edx. | |
104 __ Move(edx, Immediate(kNoAlignmentPadding)); | |
105 | |
106 Label do_not_pad, align_loop; | |
107 STATIC_ASSERT(kDoubleSize == 2 * kPointerSize); | |
108 // Align esp + 4 to a multiple of 2 * kPointerSize. | |
109 __ test(esp, Immediate(kPointerSize)); | |
110 __ j(not_zero, &do_not_pad, Label::kNear); | |
111 __ push(Immediate(0)); | |
112 __ mov(ebx, esp); | |
113 __ mov(edx, Immediate(kAlignmentPaddingPushed)); | |
114 // Copy arguments, receiver, and return address. | |
115 __ mov(ecx, Immediate(scope()->num_parameters() + 2)); | |
116 | |
117 __ bind(&align_loop); | |
118 __ mov(eax, Operand(ebx, 1 * kPointerSize)); | |
119 __ mov(Operand(ebx, 0), eax); | |
120 __ add(Operand(ebx), Immediate(kPointerSize)); | |
121 __ dec(ecx); | |
122 __ j(not_zero, &align_loop, Label::kNear); | |
123 __ mov(Operand(ebx, 0), Immediate(kAlignmentZapValue)); | |
124 __ bind(&do_not_pad); | |
125 } | |
126 } | 94 } |
127 | 95 |
128 info()->set_prologue_offset(masm_->pc_offset()); | 96 info()->set_prologue_offset(masm_->pc_offset()); |
129 if (NeedsEagerFrame()) { | 97 if (NeedsEagerFrame()) { |
130 DCHECK(!frame_is_built_); | 98 DCHECK(!frame_is_built_); |
131 frame_is_built_ = true; | 99 frame_is_built_ = true; |
132 if (info()->IsStub()) { | 100 if (info()->IsStub()) { |
133 __ StubPrologue(); | 101 __ StubPrologue(); |
134 } else { | 102 } else { |
135 __ Prologue(info()->GeneratePreagedPrologue()); | 103 __ Prologue(info()->GeneratePreagedPrologue()); |
136 } | 104 } |
137 } | 105 } |
138 | 106 |
139 if (info()->IsOptimizing() && | |
140 dynamic_frame_alignment_ && | |
141 FLAG_debug_code) { | |
142 __ test(esp, Immediate(kPointerSize)); | |
143 __ Assert(zero, kFrameIsExpectedToBeAligned); | |
144 } | |
145 | |
146 // Reserve space for the stack slots needed by the code. | 107 // Reserve space for the stack slots needed by the code. |
147 int slots = GetStackSlotCount(); | 108 int slots = GetStackSlotCount(); |
148 DCHECK(slots != 0 || !info()->IsOptimizing()); | 109 DCHECK(slots != 0 || !info()->IsOptimizing()); |
149 if (slots > 0) { | 110 if (slots > 0) { |
150 if (slots == 1) { | 111 __ sub(Operand(esp), Immediate(slots * kPointerSize)); |
151 if (dynamic_frame_alignment_) { | |
152 __ push(edx); | |
153 } else { | |
154 __ push(Immediate(kNoAlignmentPadding)); | |
155 } | |
156 } else { | |
157 if (FLAG_debug_code) { | |
158 __ sub(Operand(esp), Immediate(slots * kPointerSize)); | |
159 #ifdef _MSC_VER | 112 #ifdef _MSC_VER |
160 MakeSureStackPagesMapped(slots * kPointerSize); | 113 MakeSureStackPagesMapped(slots * kPointerSize); |
161 #endif | 114 #endif |
162 __ push(eax); | 115 if (FLAG_debug_code) { |
163 __ mov(Operand(eax), Immediate(slots)); | 116 __ push(eax); |
164 Label loop; | 117 __ mov(Operand(eax), Immediate(slots)); |
165 __ bind(&loop); | 118 Label loop; |
166 __ mov(MemOperand(esp, eax, times_4, 0), | 119 __ bind(&loop); |
167 Immediate(kSlotsZapValue)); | 120 __ mov(MemOperand(esp, eax, times_4, 0), Immediate(kSlotsZapValue)); |
168 __ dec(eax); | 121 __ dec(eax); |
169 __ j(not_zero, &loop); | 122 __ j(not_zero, &loop); |
170 __ pop(eax); | 123 __ pop(eax); |
171 } else { | |
172 __ sub(Operand(esp), Immediate(slots * kPointerSize)); | |
173 #ifdef _MSC_VER | |
174 MakeSureStackPagesMapped(slots * kPointerSize); | |
175 #endif | |
176 } | |
177 | |
178 if (support_aligned_spilled_doubles_) { | |
179 Comment(";;; Store dynamic frame alignment tag for spilled doubles"); | |
180 // Store dynamic frame alignment state in the first local. | |
181 int offset = JavaScriptFrameConstants::kDynamicAlignmentStateOffset; | |
182 if (dynamic_frame_alignment_) { | |
183 __ mov(Operand(ebp, offset), edx); | |
184 } else { | |
185 __ mov(Operand(ebp, offset), Immediate(kNoAlignmentPadding)); | |
186 } | |
187 } | |
188 } | 124 } |
189 } | 125 } |
190 | 126 |
191 // Initailize FPU state. | 127 // Initailize FPU state. |
192 __ fninit(); | 128 __ fninit(); |
193 | 129 |
194 return !is_aborted(); | 130 return !is_aborted(); |
195 } | 131 } |
196 | 132 |
197 | 133 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 } | 194 } |
259 | 195 |
260 | 196 |
261 void LCodeGen::GenerateOsrPrologue() { | 197 void LCodeGen::GenerateOsrPrologue() { |
262 // Generate the OSR entry prologue at the first unknown OSR value, or if there | 198 // Generate the OSR entry prologue at the first unknown OSR value, or if there |
263 // are none, at the OSR entrypoint instruction. | 199 // are none, at the OSR entrypoint instruction. |
264 if (osr_pc_offset_ >= 0) return; | 200 if (osr_pc_offset_ >= 0) return; |
265 | 201 |
266 osr_pc_offset_ = masm()->pc_offset(); | 202 osr_pc_offset_ = masm()->pc_offset(); |
267 | 203 |
268 // Move state of dynamic frame alignment into edx. | |
269 __ Move(edx, Immediate(kNoAlignmentPadding)); | |
270 | |
271 if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) { | |
272 Label do_not_pad, align_loop; | |
273 // Align ebp + 4 to a multiple of 2 * kPointerSize. | |
274 __ test(ebp, Immediate(kPointerSize)); | |
275 __ j(zero, &do_not_pad, Label::kNear); | |
276 __ push(Immediate(0)); | |
277 __ mov(ebx, esp); | |
278 __ mov(edx, Immediate(kAlignmentPaddingPushed)); | |
279 | |
280 // Move all parts of the frame over one word. The frame consists of: | |
281 // unoptimized frame slots, alignment state, context, frame pointer, return | |
282 // address, receiver, and the arguments. | |
283 __ mov(ecx, Immediate(scope()->num_parameters() + | |
284 5 + graph()->osr()->UnoptimizedFrameSlots())); | |
285 | |
286 __ bind(&align_loop); | |
287 __ mov(eax, Operand(ebx, 1 * kPointerSize)); | |
288 __ mov(Operand(ebx, 0), eax); | |
289 __ add(Operand(ebx), Immediate(kPointerSize)); | |
290 __ dec(ecx); | |
291 __ j(not_zero, &align_loop, Label::kNear); | |
292 __ mov(Operand(ebx, 0), Immediate(kAlignmentZapValue)); | |
293 __ sub(Operand(ebp), Immediate(kPointerSize)); | |
294 __ bind(&do_not_pad); | |
295 } | |
296 | |
297 // Save the first local, which is overwritten by the alignment state. | |
298 Operand alignment_loc = MemOperand(ebp, -3 * kPointerSize); | |
299 __ push(alignment_loc); | |
300 | |
301 // Set the dynamic frame alignment state. | |
302 __ mov(alignment_loc, edx); | |
303 | |
304 // Adjust the frame size, subsuming the unoptimized frame into the | 204 // Adjust the frame size, subsuming the unoptimized frame into the |
305 // optimized frame. | 205 // optimized frame. |
306 int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots(); | 206 int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots(); |
307 DCHECK(slots >= 1); | 207 DCHECK(slots >= 0); |
308 __ sub(esp, Immediate((slots - 1) * kPointerSize)); | 208 __ sub(esp, Immediate(slots * kPointerSize)); |
309 | |
310 // Initailize FPU state. | |
311 __ fninit(); | |
312 } | 209 } |
313 | 210 |
314 | 211 |
315 void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) { | 212 void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) { |
316 if (instr->IsCall()) { | 213 if (instr->IsCall()) { |
317 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | 214 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
318 } | 215 } |
319 if (!instr->IsLazyBailout() && !instr->IsGap()) { | 216 if (!instr->IsLazyBailout() && !instr->IsGap()) { |
320 safepoints_.BumpLastLazySafepointIndex(); | 217 safepoints_.BumpLastLazySafepointIndex(); |
321 } | 218 } |
(...skipping 2420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2742 Label true_value, done; | 2639 Label true_value, done; |
2743 __ test(eax, Operand(eax)); | 2640 __ test(eax, Operand(eax)); |
2744 __ j(condition, &true_value, Label::kNear); | 2641 __ j(condition, &true_value, Label::kNear); |
2745 __ mov(ToRegister(instr->result()), factory()->false_value()); | 2642 __ mov(ToRegister(instr->result()), factory()->false_value()); |
2746 __ jmp(&done, Label::kNear); | 2643 __ jmp(&done, Label::kNear); |
2747 __ bind(&true_value); | 2644 __ bind(&true_value); |
2748 __ mov(ToRegister(instr->result()), factory()->true_value()); | 2645 __ mov(ToRegister(instr->result()), factory()->true_value()); |
2749 __ bind(&done); | 2646 __ bind(&done); |
2750 } | 2647 } |
2751 | 2648 |
2752 | 2649 void LCodeGen::EmitReturn(LReturn* instr) { |
2753 void LCodeGen::EmitReturn(LReturn* instr, bool dynamic_frame_alignment) { | 2650 int extra_value_count = 1; |
2754 int extra_value_count = dynamic_frame_alignment ? 2 : 1; | |
2755 | 2651 |
2756 if (instr->has_constant_parameter_count()) { | 2652 if (instr->has_constant_parameter_count()) { |
2757 int parameter_count = ToInteger32(instr->constant_parameter_count()); | 2653 int parameter_count = ToInteger32(instr->constant_parameter_count()); |
2758 if (dynamic_frame_alignment && FLAG_debug_code) { | |
2759 __ cmp(Operand(esp, | |
2760 (parameter_count + extra_value_count) * kPointerSize), | |
2761 Immediate(kAlignmentZapValue)); | |
2762 __ Assert(equal, kExpectedAlignmentMarker); | |
2763 } | |
2764 __ Ret((parameter_count + extra_value_count) * kPointerSize, ecx); | 2654 __ Ret((parameter_count + extra_value_count) * kPointerSize, ecx); |
2765 } else { | 2655 } else { |
2766 DCHECK(info()->IsStub()); // Functions would need to drop one more value. | 2656 DCHECK(info()->IsStub()); // Functions would need to drop one more value. |
2767 Register reg = ToRegister(instr->parameter_count()); | 2657 Register reg = ToRegister(instr->parameter_count()); |
2768 // The argument count parameter is a smi | 2658 // The argument count parameter is a smi |
2769 __ SmiUntag(reg); | 2659 __ SmiUntag(reg); |
2770 Register return_addr_reg = reg.is(ecx) ? ebx : ecx; | 2660 Register return_addr_reg = reg.is(ecx) ? ebx : ecx; |
2771 if (dynamic_frame_alignment && FLAG_debug_code) { | |
2772 DCHECK(extra_value_count == 2); | |
2773 __ cmp(Operand(esp, reg, times_pointer_size, | |
2774 extra_value_count * kPointerSize), | |
2775 Immediate(kAlignmentZapValue)); | |
2776 __ Assert(equal, kExpectedAlignmentMarker); | |
2777 } | |
2778 | 2661 |
2779 // emit code to restore stack based on instr->parameter_count() | 2662 // emit code to restore stack based on instr->parameter_count() |
2780 __ pop(return_addr_reg); // save return address | 2663 __ pop(return_addr_reg); // save return address |
2781 if (dynamic_frame_alignment) { | |
2782 __ inc(reg); // 1 more for alignment | |
2783 } | |
2784 __ shl(reg, kPointerSizeLog2); | 2664 __ shl(reg, kPointerSizeLog2); |
2785 __ add(esp, reg); | 2665 __ add(esp, reg); |
2786 __ jmp(return_addr_reg); | 2666 __ jmp(return_addr_reg); |
2787 } | 2667 } |
2788 } | 2668 } |
2789 | 2669 |
2790 | 2670 |
2791 void LCodeGen::DoReturn(LReturn* instr) { | 2671 void LCodeGen::DoReturn(LReturn* instr) { |
2792 if (FLAG_trace && info()->IsOptimizing()) { | 2672 if (FLAG_trace && info()->IsOptimizing()) { |
2793 // Preserve the return value on the stack and rely on the runtime call | 2673 // Preserve the return value on the stack and rely on the runtime call |
2794 // to return the value in the same register. We're leaving the code | 2674 // to return the value in the same register. We're leaving the code |
2795 // managed by the register allocator and tearing down the frame, it's | 2675 // managed by the register allocator and tearing down the frame, it's |
2796 // safe to write to the context register. | 2676 // safe to write to the context register. |
2797 __ push(eax); | 2677 __ push(eax); |
2798 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2678 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
2799 __ CallRuntime(Runtime::kTraceExit); | 2679 __ CallRuntime(Runtime::kTraceExit); |
2800 } | 2680 } |
2801 if (dynamic_frame_alignment_) { | |
2802 // Fetch the state of the dynamic frame alignment. | |
2803 __ mov(edx, Operand(ebp, | |
2804 JavaScriptFrameConstants::kDynamicAlignmentStateOffset)); | |
2805 } | |
2806 if (NeedsEagerFrame()) { | 2681 if (NeedsEagerFrame()) { |
2807 __ mov(esp, ebp); | 2682 __ mov(esp, ebp); |
2808 __ pop(ebp); | 2683 __ pop(ebp); |
2809 } | 2684 } |
2810 if (dynamic_frame_alignment_) { | |
2811 Label no_padding; | |
2812 __ cmp(edx, Immediate(kNoAlignmentPadding)); | |
2813 __ j(equal, &no_padding, Label::kNear); | |
2814 | 2685 |
2815 EmitReturn(instr, true); | 2686 EmitReturn(instr); |
2816 __ bind(&no_padding); | |
2817 } | |
2818 | |
2819 EmitReturn(instr, false); | |
2820 } | 2687 } |
2821 | 2688 |
2822 | 2689 |
2823 template <class T> | 2690 template <class T> |
2824 void LCodeGen::EmitVectorLoadICRegisters(T* instr) { | 2691 void LCodeGen::EmitVectorLoadICRegisters(T* instr) { |
2825 Register vector_register = ToRegister(instr->temp_vector()); | 2692 Register vector_register = ToRegister(instr->temp_vector()); |
2826 Register slot_register = LoadWithVectorDescriptor::SlotRegister(); | 2693 Register slot_register = LoadWithVectorDescriptor::SlotRegister(); |
2827 DCHECK(vector_register.is(LoadWithVectorDescriptor::VectorRegister())); | 2694 DCHECK(vector_register.is(LoadWithVectorDescriptor::VectorRegister())); |
2828 DCHECK(slot_register.is(eax)); | 2695 DCHECK(slot_register.is(eax)); |
2829 | 2696 |
(...skipping 3062 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5892 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), context); | 5759 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), context); |
5893 } | 5760 } |
5894 | 5761 |
5895 | 5762 |
5896 #undef __ | 5763 #undef __ |
5897 | 5764 |
5898 } // namespace internal | 5765 } // namespace internal |
5899 } // namespace v8 | 5766 } // namespace v8 |
5900 | 5767 |
5901 #endif // V8_TARGET_ARCH_X87 | 5768 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |