| 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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 if (is_bound()) { | 73 if (is_bound()) { |
| 74 ASSERT(direction_ == BIDIRECTIONAL); | 74 ASSERT(direction_ == BIDIRECTIONAL); |
| 75 // Backward branch. We have an expected frame to merge to on the | 75 // Backward branch. We have an expected frame to merge to on the |
| 76 // backward edge. | 76 // backward edge. |
| 77 | 77 |
| 78 // Swap the current frame for a copy (we do the swapping to get | 78 // Swap the current frame for a copy (we do the swapping to get |
| 79 // the off-frame registers off the fall through) to use for the | 79 // the off-frame registers off the fall through) to use for the |
| 80 // branch. | 80 // branch. |
| 81 VirtualFrame* fall_through_frame = cgen()->frame(); | 81 VirtualFrame* fall_through_frame = cgen()->frame(); |
| 82 VirtualFrame* branch_frame = new VirtualFrame(fall_through_frame); | 82 VirtualFrame* branch_frame = new VirtualFrame(fall_through_frame); |
| 83 RegisterFile non_frame_registers = RegisterAllocator::Reserved(); | 83 RegisterFile non_frame_registers; |
| 84 cgen()->SetFrame(branch_frame, &non_frame_registers); | 84 cgen()->SetFrame(branch_frame, &non_frame_registers); |
| 85 | 85 |
| 86 // Check if we can avoid merge code. | 86 // Check if we can avoid merge code. |
| 87 cgen()->frame()->PrepareMergeTo(entry_frame_); | 87 cgen()->frame()->PrepareMergeTo(entry_frame_); |
| 88 if (cgen()->frame()->Equals(entry_frame_)) { | 88 if (cgen()->frame()->Equals(entry_frame_)) { |
| 89 // Branch right in to the block. | 89 // Branch right in to the block. |
| 90 cgen()->DeleteFrame(); | 90 cgen()->DeleteFrame(); |
| 91 __ b(cc, &entry_label_); | 91 __ b(cc, &entry_label_); |
| 92 cgen()->SetFrame(fall_through_frame, &non_frame_registers); | 92 cgen()->SetFrame(fall_through_frame, &non_frame_registers); |
| 93 return; | 93 return; |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 // block. | 156 // block. |
| 157 ASSERT(!cgen()->has_valid_frame() || cgen()->HasValidEntryRegisters()); | 157 ASSERT(!cgen()->has_valid_frame() || cgen()->HasValidEntryRegisters()); |
| 158 | 158 |
| 159 if (direction_ == FORWARD_ONLY) { | 159 if (direction_ == FORWARD_ONLY) { |
| 160 // A simple case: no forward jumps and no possible backward jumps. | 160 // A simple case: no forward jumps and no possible backward jumps. |
| 161 if (!is_linked()) { | 161 if (!is_linked()) { |
| 162 // The stack pointer can be floating above the top of the | 162 // The stack pointer can be floating above the top of the |
| 163 // virtual frame before the bind. Afterward, it should not. | 163 // virtual frame before the bind. Afterward, it should not. |
| 164 ASSERT(cgen()->has_valid_frame()); | 164 ASSERT(cgen()->has_valid_frame()); |
| 165 VirtualFrame* frame = cgen()->frame(); | 165 VirtualFrame* frame = cgen()->frame(); |
| 166 int difference = | 166 int difference = frame->stack_pointer_ - (frame->element_count() - 1); |
| 167 frame->stack_pointer_ - (frame->elements_.length() - 1); | |
| 168 if (difference > 0) { | 167 if (difference > 0) { |
| 169 frame->stack_pointer_ -= difference; | 168 frame->stack_pointer_ -= difference; |
| 170 __ add(sp, sp, Operand(difference * kPointerSize)); | 169 __ add(sp, sp, Operand(difference * kPointerSize)); |
| 171 } | 170 } |
| 172 __ bind(&entry_label_); | 171 __ bind(&entry_label_); |
| 173 return; | 172 return; |
| 174 } | 173 } |
| 175 | 174 |
| 176 // Another simple case: no fall through, a single forward jump, | 175 // Another simple case: no fall through, a single forward jump, |
| 177 // and no possible backward jumps. | 176 // and no possible backward jumps. |
| 178 if (!cgen()->has_valid_frame() && reaching_frames_.length() == 1) { | 177 if (!cgen()->has_valid_frame() && reaching_frames_.length() == 1) { |
| 179 // Pick up the only reaching frame, take ownership of it, and | 178 // Pick up the only reaching frame, take ownership of it, and |
| 180 // use it for the block about to be emitted. | 179 // use it for the block about to be emitted. |
| 181 VirtualFrame* frame = reaching_frames_[0]; | 180 VirtualFrame* frame = reaching_frames_[0]; |
| 182 RegisterFile reserved = RegisterAllocator::Reserved(); | 181 RegisterFile empty; |
| 183 cgen()->SetFrame(frame, &reserved); | 182 cgen()->SetFrame(frame, &empty); |
| 184 reaching_frames_[0] = NULL; | 183 reaching_frames_[0] = NULL; |
| 185 __ bind(&merge_labels_[0]); | 184 __ bind(&merge_labels_[0]); |
| 186 | 185 |
| 187 // The stack pointer can be floating above the top of the | 186 // The stack pointer can be floating above the top of the |
| 188 // virtual frame before the bind. Afterward, it should not. | 187 // virtual frame before the bind. Afterward, it should not. |
| 189 int difference = | 188 int difference = frame->stack_pointer_ - (frame->element_count() - 1); |
| 190 frame->stack_pointer_ - (frame->elements_.length() - 1); | |
| 191 if (difference > 0) { | 189 if (difference > 0) { |
| 192 frame->stack_pointer_ -= difference; | 190 frame->stack_pointer_ -= difference; |
| 193 __ add(sp, sp, Operand(difference * kPointerSize)); | 191 __ add(sp, sp, Operand(difference * kPointerSize)); |
| 194 } | 192 } |
| 195 __ bind(&entry_label_); | 193 __ bind(&entry_label_); |
| 196 return; | 194 return; |
| 197 } | 195 } |
| 198 } | 196 } |
| 199 | 197 |
| 200 // If there is a current frame, record it as the fall-through. It | 198 // If there is a current frame, record it as the fall-through. It |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 // We could have a valid frame as the fall through to the | 238 // We could have a valid frame as the fall through to the |
| 241 // binding site or as the fall through from a previous merge | 239 // binding site or as the fall through from a previous merge |
| 242 // code block. Jump around the code we are about to | 240 // code block. Jump around the code we are about to |
| 243 // generate. | 241 // generate. |
| 244 if (cgen()->has_valid_frame()) { | 242 if (cgen()->has_valid_frame()) { |
| 245 cgen()->DeleteFrame(); | 243 cgen()->DeleteFrame(); |
| 246 __ b(&entry_label_); | 244 __ b(&entry_label_); |
| 247 } | 245 } |
| 248 // Pick up the frame for this block. Assume ownership if | 246 // Pick up the frame for this block. Assume ownership if |
| 249 // there cannot be backward jumps. | 247 // there cannot be backward jumps. |
| 250 RegisterFile reserved = RegisterAllocator::Reserved(); | 248 RegisterFile empty; |
| 251 if (direction_ == BIDIRECTIONAL) { | 249 if (direction_ == BIDIRECTIONAL) { |
| 252 cgen()->SetFrame(new VirtualFrame(frame), &reserved); | 250 cgen()->SetFrame(new VirtualFrame(frame), &empty); |
| 253 } else { | 251 } else { |
| 254 cgen()->SetFrame(frame, &reserved); | 252 cgen()->SetFrame(frame, &empty); |
| 255 reaching_frames_[i] = NULL; | 253 reaching_frames_[i] = NULL; |
| 256 } | 254 } |
| 257 __ bind(&merge_labels_[i]); | 255 __ bind(&merge_labels_[i]); |
| 258 | 256 |
| 259 // Loop over the remaining (non-null) reaching frames, | 257 // Loop over the remaining (non-null) reaching frames, |
| 260 // looking for any that can share merge code with this one. | 258 // looking for any that can share merge code with this one. |
| 261 for (int j = 0; j < i; j++) { | 259 for (int j = 0; j < i; j++) { |
| 262 VirtualFrame* other = reaching_frames_[j]; | 260 VirtualFrame* other = reaching_frames_[j]; |
| 263 if (other != NULL && other->Equals(cgen()->frame())) { | 261 if (other != NULL && other->Equals(cgen()->frame())) { |
| 264 // Set the reaching frame element to null to avoid | 262 // Set the reaching frame element to null to avoid |
| 265 // processing it later, and then bind its entry label. | 263 // processing it later, and then bind its entry label. |
| 266 reaching_frames_[j] = NULL; | 264 reaching_frames_[j] = NULL; |
| 267 __ bind(&merge_labels_[j]); | 265 __ bind(&merge_labels_[j]); |
| 268 } | 266 } |
| 269 } | 267 } |
| 270 | 268 |
| 271 // Emit the merge code. | 269 // Emit the merge code. |
| 272 cgen()->frame()->MergeTo(entry_frame_); | 270 cgen()->frame()->MergeTo(entry_frame_); |
| 273 } else if (i == reaching_frames_.length() - 1 && had_fall_through) { | 271 } else if (i == reaching_frames_.length() - 1 && had_fall_through) { |
| 274 // If this is the fall through, and it didn't need merge | 272 // If this is the fall through, and it didn't need merge |
| 275 // code, we need to pick up the frame so we can jump around | 273 // code, we need to pick up the frame so we can jump around |
| 276 // subsequent merge blocks if necessary. | 274 // subsequent merge blocks if necessary. |
| 277 RegisterFile reserved = RegisterAllocator::Reserved(); | 275 RegisterFile empty; |
| 278 cgen()->SetFrame(frame, &reserved); | 276 cgen()->SetFrame(frame, &empty); |
| 279 reaching_frames_[i] = NULL; | 277 reaching_frames_[i] = NULL; |
| 280 } | 278 } |
| 281 } | 279 } |
| 282 } | 280 } |
| 283 | 281 |
| 284 // The code generator may not have a current frame if there was no | 282 // The code generator may not have a current frame if there was no |
| 285 // fall through and none of the reaching frames needed merging. | 283 // fall through and none of the reaching frames needed merging. |
| 286 // In that case, clone the entry frame as the current frame. | 284 // In that case, clone the entry frame as the current frame. |
| 287 if (!cgen()->has_valid_frame()) { | 285 if (!cgen()->has_valid_frame()) { |
| 288 RegisterFile reserved_registers = RegisterAllocator::Reserved(); | 286 RegisterFile empty; |
| 289 cgen()->SetFrame(new VirtualFrame(entry_frame_), &reserved_registers); | 287 cgen()->SetFrame(new VirtualFrame(entry_frame_), &empty); |
| 290 } | 288 } |
| 291 | 289 |
| 292 // There may be unprocessed reaching frames that did not need | 290 // There may be unprocessed reaching frames that did not need |
| 293 // merge code. They will have unbound merge labels. Bind their | 291 // merge code. They will have unbound merge labels. Bind their |
| 294 // merge labels to be the same as the entry label and deallocate | 292 // merge labels to be the same as the entry label and deallocate |
| 295 // them. | 293 // them. |
| 296 for (int i = 0; i < reaching_frames_.length(); i++) { | 294 for (int i = 0; i < reaching_frames_.length(); i++) { |
| 297 if (!merge_labels_[i].is_bound()) { | 295 if (!merge_labels_[i].is_bound()) { |
| 298 reaching_frames_[i] = NULL; | 296 reaching_frames_[i] = NULL; |
| 299 __ bind(&merge_labels_[i]); | 297 __ bind(&merge_labels_[i]); |
| 300 } | 298 } |
| 301 } | 299 } |
| 302 | 300 |
| 303 // There are non-NULL reaching frames with bound labels for each | 301 // There are non-NULL reaching frames with bound labels for each |
| 304 // merge block, but only on backward targets. | 302 // merge block, but only on backward targets. |
| 305 } else { | 303 } else { |
| 306 // There were no forward jumps. There must be a current frame and | 304 // There were no forward jumps. There must be a current frame and |
| 307 // this must be a bidirectional target. | 305 // this must be a bidirectional target. |
| 308 ASSERT(reaching_frames_.length() == 1); | 306 ASSERT(reaching_frames_.length() == 1); |
| 309 ASSERT(reaching_frames_[0] != NULL); | 307 ASSERT(reaching_frames_[0] != NULL); |
| 310 ASSERT(direction_ == BIDIRECTIONAL); | 308 ASSERT(direction_ == BIDIRECTIONAL); |
| 311 | 309 |
| 312 // Use a copy of the reaching frame so the original can be saved | 310 // Use a copy of the reaching frame so the original can be saved |
| 313 // for possible reuse as a backward merge block. | 311 // for possible reuse as a backward merge block. |
| 314 RegisterFile reserved = RegisterAllocator::Reserved(); | 312 RegisterFile empty; |
| 315 cgen()->SetFrame(new VirtualFrame(reaching_frames_[0]), &reserved); | 313 cgen()->SetFrame(new VirtualFrame(reaching_frames_[0]), &empty); |
| 316 __ bind(&merge_labels_[0]); | 314 __ bind(&merge_labels_[0]); |
| 317 cgen()->frame()->MergeTo(entry_frame_); | 315 cgen()->frame()->MergeTo(entry_frame_); |
| 318 } | 316 } |
| 319 | 317 |
| 320 __ bind(&entry_label_); | 318 __ bind(&entry_label_); |
| 321 } | 319 } |
| 322 | 320 |
| 323 #undef __ | 321 #undef __ |
| 324 | 322 |
| 325 | 323 |
| 326 } } // namespace v8::internal | 324 } } // namespace v8::internal |
| OLD | NEW |