OLD | NEW |
1 // Copyright 2008 the V8 project authors. All rights reserved. | 1 // Copyright 2008 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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 // Preconfigured entry frame is not used on ARM. | 55 // Preconfigured entry frame is not used on ARM. |
56 ASSERT(entry_frame_ == NULL); | 56 ASSERT(entry_frame_ == NULL); |
57 // Forward jump. The current frame is added to the end of the list | 57 // Forward jump. The current frame is added to the end of the list |
58 // of frames reaching the target block and a jump to the merge code | 58 // of frames reaching the target block and a jump to the merge code |
59 // is emitted. | 59 // is emitted. |
60 AddReachingFrame(cgen_->frame()); | 60 AddReachingFrame(cgen_->frame()); |
61 RegisterFile empty; | 61 RegisterFile empty; |
62 cgen_->SetFrame(NULL, &empty); | 62 cgen_->SetFrame(NULL, &empty); |
63 __ jmp(&merge_labels_.last()); | 63 __ jmp(&merge_labels_.last()); |
64 } | 64 } |
65 | |
66 is_linked_ = !is_bound_; | |
67 } | 65 } |
68 | 66 |
69 | 67 |
70 void JumpTarget::DoBranch(Condition cc, Hint ignored) { | 68 void JumpTarget::DoBranch(Condition cc, Hint ignored) { |
71 ASSERT(cgen_ != NULL); | 69 ASSERT(cgen_ != NULL); |
72 ASSERT(cgen_->has_valid_frame()); | 70 ASSERT(cgen_->has_valid_frame()); |
73 | 71 |
74 if (is_bound()) { | 72 if (is_bound()) { |
75 ASSERT(direction_ == BIDIRECTIONAL); | 73 ASSERT(direction_ == BIDIRECTIONAL); |
76 // Backward branch. We have an expected frame to merge to on the | 74 // Backward branch. We have an expected frame to merge to on the |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 __ bind(&original_fall_through); | 115 __ bind(&original_fall_through); |
118 | 116 |
119 } else { | 117 } else { |
120 // Preconfigured entry frame is not used on ARM. | 118 // Preconfigured entry frame is not used on ARM. |
121 ASSERT(entry_frame_ == NULL); | 119 ASSERT(entry_frame_ == NULL); |
122 // Forward branch. A copy of the current frame is added to the end | 120 // Forward branch. A copy of the current frame is added to the end |
123 // of the list of frames reaching the target block and a branch to | 121 // of the list of frames reaching the target block and a branch to |
124 // the merge code is emitted. | 122 // the merge code is emitted. |
125 AddReachingFrame(new VirtualFrame(cgen_->frame())); | 123 AddReachingFrame(new VirtualFrame(cgen_->frame())); |
126 __ b(cc, &merge_labels_.last()); | 124 __ b(cc, &merge_labels_.last()); |
127 is_linked_ = true; | |
128 } | 125 } |
129 } | 126 } |
130 | 127 |
131 | 128 |
132 void JumpTarget::Call() { | 129 void JumpTarget::Call() { |
133 // Call is used to push the address of the catch block on the stack as | 130 // Call is used to push the address of the catch block on the stack as |
134 // a return address when compiling try/catch and try/finally. We | 131 // a return address when compiling try/catch and try/finally. We |
135 // fully spill the frame before making the call. The expected frame | 132 // fully spill the frame before making the call. The expected frame |
136 // at the label (which should be the only one) is the spilled current | 133 // at the label (which should be the only one) is the spilled current |
137 // frame plus an in-memory return address. The "fall-through" frame | 134 // frame plus an in-memory return address. The "fall-through" frame |
138 // at the return site is the spilled current frame. | 135 // at the return site is the spilled current frame. |
139 ASSERT(cgen_ != NULL); | 136 ASSERT(cgen_ != NULL); |
140 ASSERT(cgen_->has_valid_frame()); | 137 ASSERT(cgen_->has_valid_frame()); |
141 // There are no non-frame references across the call. | 138 // There are no non-frame references across the call. |
142 ASSERT(cgen_->HasValidEntryRegisters()); | 139 ASSERT(cgen_->HasValidEntryRegisters()); |
143 ASSERT(!is_linked()); | 140 ASSERT(!is_linked()); |
144 | 141 |
145 cgen_->frame()->SpillAll(); | 142 cgen_->frame()->SpillAll(); |
146 VirtualFrame* target_frame = new VirtualFrame(cgen_->frame()); | 143 VirtualFrame* target_frame = new VirtualFrame(cgen_->frame()); |
147 target_frame->Adjust(1); | 144 target_frame->Adjust(1); |
148 // We do not expect a call with a preconfigured entry frame. | 145 // We do not expect a call with a preconfigured entry frame. |
149 ASSERT(entry_frame_ == NULL); | 146 ASSERT(entry_frame_ == NULL); |
150 AddReachingFrame(target_frame); | 147 AddReachingFrame(target_frame); |
151 __ bl(&merge_labels_.last()); | 148 __ bl(&merge_labels_.last()); |
152 | |
153 is_linked_ = !is_bound_; | |
154 } | 149 } |
155 | 150 |
156 | 151 |
157 void JumpTarget::DoBind(int mergable_elements) { | 152 void JumpTarget::DoBind(int mergable_elements) { |
158 ASSERT(cgen_ != NULL); | 153 ASSERT(cgen_ != NULL); |
159 ASSERT(!is_bound()); | 154 ASSERT(!is_bound()); |
160 | 155 |
161 // Live non-frame registers are not allowed at the start of a basic | 156 // Live non-frame registers are not allowed at the start of a basic |
162 // block. | 157 // block. |
163 ASSERT(!cgen_->has_valid_frame() || cgen_->HasValidEntryRegisters()); | 158 ASSERT(!cgen_->has_valid_frame() || cgen_->HasValidEntryRegisters()); |
164 | 159 |
165 if (direction_ == FORWARD_ONLY) { | 160 if (direction_ == FORWARD_ONLY) { |
166 // A simple case: no forward jumps and no possible backward jumps. | 161 // A simple case: no forward jumps and no possible backward jumps. |
167 if (!is_linked()) { | 162 if (!is_linked()) { |
168 // The stack pointer can be floating above the top of the | 163 // The stack pointer can be floating above the top of the |
169 // virtual frame before the bind. Afterward, it should not. | 164 // virtual frame before the bind. Afterward, it should not. |
170 ASSERT(cgen_->has_valid_frame()); | 165 ASSERT(cgen_->has_valid_frame()); |
171 VirtualFrame* frame = cgen_->frame(); | 166 VirtualFrame* frame = cgen_->frame(); |
172 int difference = | 167 int difference = |
173 frame->stack_pointer_ - (frame->elements_.length() - 1); | 168 frame->stack_pointer_ - (frame->elements_.length() - 1); |
174 if (difference > 0) { | 169 if (difference > 0) { |
175 frame->stack_pointer_ -= difference; | 170 frame->stack_pointer_ -= difference; |
176 __ add(sp, sp, Operand(difference * kPointerSize)); | 171 __ add(sp, sp, Operand(difference * kPointerSize)); |
177 } | 172 } |
178 | 173 __ bind(&entry_label_); |
179 is_bound_ = true; | |
180 return; | 174 return; |
181 } | 175 } |
182 | 176 |
183 // Another simple case: no fall through, a single forward jump, | 177 // Another simple case: no fall through, a single forward jump, |
184 // and no possible backward jumps. | 178 // and no possible backward jumps. |
185 if (!cgen_->has_valid_frame() && reaching_frames_.length() == 1) { | 179 if (!cgen_->has_valid_frame() && reaching_frames_.length() == 1) { |
186 // Pick up the only reaching frame, take ownership of it, and | 180 // Pick up the only reaching frame, take ownership of it, and |
187 // use it for the block about to be emitted. | 181 // use it for the block about to be emitted. |
188 VirtualFrame* frame = reaching_frames_[0]; | 182 VirtualFrame* frame = reaching_frames_[0]; |
189 RegisterFile reserved = RegisterAllocator::Reserved(); | 183 RegisterFile reserved = RegisterAllocator::Reserved(); |
190 cgen_->SetFrame(frame, &reserved); | 184 cgen_->SetFrame(frame, &reserved); |
191 reaching_frames_[0] = NULL; | 185 reaching_frames_[0] = NULL; |
192 __ bind(&merge_labels_[0]); | 186 __ bind(&merge_labels_[0]); |
193 | 187 |
194 // The stack pointer can be floating above the top of the | 188 // The stack pointer can be floating above the top of the |
195 // virtual frame before the bind. Afterward, it should not. | 189 // virtual frame before the bind. Afterward, it should not. |
196 int difference = | 190 int difference = |
197 frame->stack_pointer_ - (frame->elements_.length() - 1); | 191 frame->stack_pointer_ - (frame->elements_.length() - 1); |
198 if (difference > 0) { | 192 if (difference > 0) { |
199 frame->stack_pointer_ -= difference; | 193 frame->stack_pointer_ -= difference; |
200 __ add(sp, sp, Operand(difference * kPointerSize)); | 194 __ add(sp, sp, Operand(difference * kPointerSize)); |
201 } | 195 } |
202 | 196 __ bind(&entry_label_); |
203 is_linked_ = false; | |
204 is_bound_ = true; | |
205 return; | 197 return; |
206 } | 198 } |
207 } | 199 } |
208 | 200 |
209 // If there is a current frame, record it as the fall-through. It | 201 // If there is a current frame, record it as the fall-through. It |
210 // is owned by the reaching frames for now. | 202 // is owned by the reaching frames for now. |
211 bool had_fall_through = false; | 203 bool had_fall_through = false; |
212 if (cgen_->has_valid_frame()) { | 204 if (cgen_->has_valid_frame()) { |
213 had_fall_through = true; | 205 had_fall_through = true; |
214 AddReachingFrame(cgen_->frame()); // Return value ignored. | 206 AddReachingFrame(cgen_->frame()); // Return value ignored. |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 } | 283 } |
292 | 284 |
293 // The code generator may not have a current frame if there was no | 285 // The code generator may not have a current frame if there was no |
294 // fall through and none of the reaching frames needed merging. | 286 // fall through and none of the reaching frames needed merging. |
295 // In that case, clone the entry frame as the current frame. | 287 // In that case, clone the entry frame as the current frame. |
296 if (!cgen_->has_valid_frame()) { | 288 if (!cgen_->has_valid_frame()) { |
297 RegisterFile reserved_registers = RegisterAllocator::Reserved(); | 289 RegisterFile reserved_registers = RegisterAllocator::Reserved(); |
298 cgen_->SetFrame(new VirtualFrame(entry_frame_), &reserved_registers); | 290 cgen_->SetFrame(new VirtualFrame(entry_frame_), &reserved_registers); |
299 } | 291 } |
300 | 292 |
301 // There is certainly a current frame equal to the entry frame. | |
302 // Bind the entry frame label. | |
303 __ bind(&entry_label_); | |
304 | |
305 // There may be unprocessed reaching frames that did not need | 293 // There may be unprocessed reaching frames that did not need |
306 // merge code. They will have unbound merge labels. Bind their | 294 // merge code. They will have unbound merge labels. Bind their |
307 // merge labels to be the same as the entry label and deallocate | 295 // merge labels to be the same as the entry label and deallocate |
308 // them. | 296 // them. |
309 for (int i = 0; i < reaching_frames_.length(); i++) { | 297 for (int i = 0; i < reaching_frames_.length(); i++) { |
310 if (!merge_labels_[i].is_bound()) { | 298 if (!merge_labels_[i].is_bound()) { |
311 reaching_frames_[i] = NULL; | 299 reaching_frames_[i] = NULL; |
312 __ bind(&merge_labels_[i]); | 300 __ bind(&merge_labels_[i]); |
313 } | 301 } |
314 } | 302 } |
315 | 303 |
316 // There are non-NULL reaching frames with bound labels for each | 304 // There are non-NULL reaching frames with bound labels for each |
317 // merge block, but only on backward targets. | 305 // merge block, but only on backward targets. |
318 } else { | 306 } else { |
319 // There were no forward jumps. There must be a current frame and | 307 // There were no forward jumps. There must be a current frame and |
320 // this must be a bidirectional target. | 308 // this must be a bidirectional target. |
321 ASSERT(reaching_frames_.length() == 1); | 309 ASSERT(reaching_frames_.length() == 1); |
322 ASSERT(reaching_frames_[0] != NULL); | 310 ASSERT(reaching_frames_[0] != NULL); |
323 ASSERT(direction_ == BIDIRECTIONAL); | 311 ASSERT(direction_ == BIDIRECTIONAL); |
324 | 312 |
325 // Use a copy of the reaching frame so the original can be saved | 313 // Use a copy of the reaching frame so the original can be saved |
326 // for possible reuse as a backward merge block. | 314 // for possible reuse as a backward merge block. |
327 RegisterFile reserved = RegisterAllocator::Reserved(); | 315 RegisterFile reserved = RegisterAllocator::Reserved(); |
328 cgen_->SetFrame(new VirtualFrame(reaching_frames_[0]), &reserved); | 316 cgen_->SetFrame(new VirtualFrame(reaching_frames_[0]), &reserved); |
329 __ bind(&merge_labels_[0]); | 317 __ bind(&merge_labels_[0]); |
330 cgen_->frame()->MergeTo(entry_frame_); | 318 cgen_->frame()->MergeTo(entry_frame_); |
331 __ bind(&entry_label_); | |
332 } | 319 } |
333 | 320 |
334 is_linked_ = false; | 321 __ bind(&entry_label_); |
335 is_bound_ = true; | |
336 } | 322 } |
337 | 323 |
338 #undef __ | 324 #undef __ |
339 | 325 |
340 | 326 |
341 } } // namespace v8::internal | 327 } } // namespace v8::internal |
OLD | NEW |