Chromium Code Reviews| 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 20 matching lines...) Expand all Loading... | |
| 31 #include "jump-target.h" | 31 #include "jump-target.h" |
| 32 | 32 |
| 33 namespace v8 { namespace internal { | 33 namespace v8 { namespace internal { |
| 34 | 34 |
| 35 // ------------------------------------------------------------------------- | 35 // ------------------------------------------------------------------------- |
| 36 // JumpTarget implementation. | 36 // JumpTarget implementation. |
| 37 | 37 |
| 38 #define __ masm_-> | 38 #define __ masm_-> |
| 39 | 39 |
| 40 JumpTarget::JumpTarget(CodeGenerator* cgen) | 40 JumpTarget::JumpTarget(CodeGenerator* cgen) |
| 41 : expected_frame_(NULL), | 41 : cgen_(cgen), |
| 42 cgen_(cgen), | 42 reaching_frames_(0), |
| 43 masm_(cgen->masm()) { | 43 merge_labels_(0), |
| 44 expected_frame_(NULL) { | |
| 45 ASSERT(cgen_ != NULL); | |
| 46 masm_ = cgen_->masm(); | |
| 44 } | 47 } |
| 45 | 48 |
| 46 | 49 |
| 47 JumpTarget::JumpTarget() | 50 JumpTarget::JumpTarget() |
| 48 : expected_frame_(NULL), | 51 : cgen_(NULL), |
| 49 cgen_(NULL), | 52 masm_(NULL), |
| 50 masm_(NULL) { | 53 reaching_frames_(0), |
| 54 merge_labels_(0), | |
| 55 expected_frame_(NULL) { | |
| 51 } | 56 } |
| 52 | 57 |
| 53 | 58 |
| 54 void JumpTarget::set_code_generator(CodeGenerator* cgen) { | 59 void JumpTarget::set_code_generator(CodeGenerator* cgen) { |
| 55 ASSERT(cgen != NULL); | 60 ASSERT(cgen != NULL); |
| 56 ASSERT(cgen_ == NULL); | 61 ASSERT(cgen_ == NULL); |
| 57 cgen_ = cgen; | 62 cgen_ = cgen; |
| 58 masm_ = cgen->masm(); | 63 masm_ = cgen->masm(); |
| 59 } | 64 } |
| 60 | 65 |
| 61 | 66 |
| 62 void JumpTarget::Jump() { | 67 void JumpTarget::Jump() { |
| 63 // Precondition: there is a current frame. There may or may not be an | |
| 64 // expected frame at the label. | |
| 65 ASSERT(cgen_ != NULL); | 68 ASSERT(cgen_ != NULL); |
| 69 ASSERT(cgen_->has_valid_frame()); | |
| 66 ASSERT(!cgen_->has_cc()); | 70 ASSERT(!cgen_->has_cc()); |
| 67 | 71 // Live non-frame registers are not allowed at unconditional jumps |
| 68 VirtualFrame* current_frame = cgen_->frame(); | 72 // because we have no way of invalidating the corresponding results |
| 69 ASSERT(current_frame != NULL); | 73 // which are still live in the C++ code. |
| 70 ASSERT(cgen_->HasValidEntryRegisters()); | 74 ASSERT(cgen_->HasValidEntryRegisters()); |
| 71 | 75 |
| 72 if (expected_frame_ == NULL) { | 76 if (is_bound()) { |
| 73 current_frame->MakeMergable(); | 77 // Backward jump. There is an expected frame to merge to. |
| 74 expected_frame_ = current_frame; | 78 cgen_->frame()->MergeTo(expected_frame_); |
| 75 ASSERT(cgen_->HasValidEntryRegisters()); | 79 cgen_->DeleteFrame(); |
| 76 RegisterFile ignored; | 80 __ jmp(&entry_label_); |
| 77 cgen_->SetFrame(NULL, &ignored); | |
| 78 } else { | 81 } else { |
| 79 current_frame->MergeTo(expected_frame_); | 82 // Forward jump. The current frame is added to the end of the list |
| 80 ASSERT(cgen_->HasValidEntryRegisters()); | 83 // of frames reaching the target block and a jump to the merge code |
| 81 cgen_->DeleteFrame(); | 84 // is emitted. |
| 85 AddReachingFrame(cgen_->frame()); | |
| 86 RegisterFile empty; | |
| 87 cgen_->SetFrame(NULL, &empty); | |
| 88 __ jmp(&merge_labels_.last()); | |
| 82 } | 89 } |
| 83 | |
| 84 __ jmp(&label_); | |
| 85 // Postcondition: there is no current frame but there is an expected frame | |
| 86 // at the label. | |
| 87 } | 90 } |
| 88 | 91 |
| 89 | 92 |
| 90 void JumpTarget::Jump(Result* arg) { | 93 void JumpTarget::Jump(Result* arg) { |
| 91 ASSERT(cgen_ != NULL); | 94 ASSERT(cgen_ != NULL); |
| 92 ASSERT(cgen_->has_valid_frame()); | 95 ASSERT(cgen_->has_valid_frame()); |
| 93 | 96 |
| 94 cgen_->frame()->Push(arg); | 97 cgen_->frame()->Push(arg); |
| 95 Jump(); | 98 Jump(); |
| 96 } | 99 } |
| 97 | 100 |
| 98 | 101 |
| 99 void JumpTarget::Branch(Condition cc, Hint hint) { | 102 void JumpTarget::Branch(Condition cc, Hint hint) { |
| 100 // Precondition: there is a current frame. There may or may not be an | |
| 101 // expected frame at the label. | |
| 102 ASSERT(cgen_ != NULL); | 103 ASSERT(cgen_ != NULL); |
| 103 ASSERT(masm_ != NULL); | 104 ASSERT(cgen_->has_valid_frame()); |
| 105 ASSERT(!cgen_->has_cc()); | |
| 104 ASSERT(!cgen_->has_cc()); | 106 ASSERT(!cgen_->has_cc()); |
|
William Hesse
2009/01/15 12:21:54
This looks like a duplicate line.
Kevin Millikin (Chromium)
2009/01/15 13:08:18
Oops. Fixed.
| |
| 105 | 107 |
| 106 VirtualFrame* current_frame = cgen_->frame(); | 108 if (is_bound()) { |
| 107 ASSERT(current_frame != NULL); | 109 // Backward branch. We have an expected frame to merge to on the |
| 108 | 110 // backward edge. We negate the condition and emit the merge code |
| 109 if (expected_frame_ == NULL) { | 111 // here. |
| 110 expected_frame_ = new VirtualFrame(current_frame); | |
| 111 // For a branch, the frame at the fall-through basic block (not labeled) | |
| 112 // does not need to be mergable, but only the other (labeled) one. That | |
| 113 // is achieved by reversing the condition and emitting the make mergable | |
| 114 // code as the actual fall-through block. | |
| 115 // | 112 // |
| 116 // TODO(): This is necessary only when MakeMergable will generate code. | 113 // TODO(): we should try to avoid negating the condition in the case |
| 114 // where there is no merge code to emit. Otherwise, we emit a | |
| 115 // branch around an unconditional jump. | |
| 117 Label original_fall_through; | 116 Label original_fall_through; |
| 118 __ j(NegateCondition(cc), &original_fall_through, NegateHint(hint)); | 117 __ j(NegateCondition(cc), &original_fall_through, NegateHint(hint)); |
| 119 expected_frame_->MakeMergable(); | 118 // Swap the current frame for a copy of it, saving non-frame |
| 120 __ jmp(&label_); | 119 // register reference counts and invalidating all non-frame register |
| 121 __ bind(&original_fall_through); | 120 // references except the reserved ones on the backward edge. |
| 122 } else { | 121 VirtualFrame* original_frame = cgen_->frame(); |
| 123 // We negate the condition and emit the code to merge to the expected | 122 VirtualFrame* working_frame = new VirtualFrame(original_frame); |
| 124 // frame immediately. | 123 RegisterFile non_frame_registers = RegisterAllocator::Reserved(); |
| 125 // | |
| 126 // TODO(): This should be replaced with a solution that emits the | |
| 127 // merge code for forward CFG edges at the appropriate entry to the | |
| 128 // target block. | |
| 129 Label original_fall_through; | |
| 130 __ j(NegateCondition(cc), &original_fall_through, NegateHint(hint)); | |
| 131 VirtualFrame* working_frame = new VirtualFrame(current_frame); | |
| 132 | |
| 133 // Switch to the working frame for the merge code with only the reserved | |
| 134 // registers referenced outside the frame. Explicitly setting | |
| 135 // references here is ugly, but temporary. | |
| 136 RegisterFile non_frame_registers; | |
| 137 non_frame_registers.Use(esi); | |
| 138 non_frame_registers.Use(ebp); | |
| 139 non_frame_registers.Use(esp); | |
| 140 cgen_->SetFrame(working_frame, &non_frame_registers); | 124 cgen_->SetFrame(working_frame, &non_frame_registers); |
| 141 | 125 |
| 142 working_frame->MergeTo(expected_frame_); | 126 working_frame->MergeTo(expected_frame_); |
| 143 ASSERT(cgen_->HasValidEntryRegisters()); | 127 cgen_->DeleteFrame(); |
| 144 __ jmp(&label_); | 128 __ jmp(&entry_label_); |
| 145 | 129 |
| 146 // Restore the current frame and its associated non-frame registers. | 130 // Restore the frame and its associated non-frame registers. |
| 147 cgen_->SetFrame(current_frame, &non_frame_registers); | 131 cgen_->SetFrame(original_frame, &non_frame_registers); |
| 148 delete working_frame; | |
| 149 __ bind(&original_fall_through); | 132 __ bind(&original_fall_through); |
| 133 } else { | |
| 134 // Forward branch. A copy of the current frame is added to the end | |
| 135 // of the list of frames reaching the target block and a branch to | |
| 136 // the merge code is emitted. | |
| 137 AddReachingFrame(new VirtualFrame(cgen_->frame())); | |
| 138 __ j(cc, &merge_labels_.last(), hint); | |
| 150 } | 139 } |
| 151 // Postcondition: there is both a current frame and an expected frame at | |
| 152 // the label and they match. | |
| 153 } | 140 } |
| 154 | 141 |
| 155 | 142 |
| 143 #ifdef DEBUG | |
| 144 #define DECLARE_ARGCHECK_VARS(name) \ | |
| 145 Result::Type name##_type = name->type(); \ | |
| 146 Register name##_reg = name->is_register() ? name->reg() : no_reg | |
| 147 | |
| 148 #define ASSERT_ARGCHECK(name) \ | |
| 149 ASSERT(name->type() == name##_type); \ | |
| 150 ASSERT(!name->is_register() || name->reg().is(name##_reg)) | |
| 151 | |
| 152 #else | |
| 153 #define DECLARE_ARGCHECK_VARS(name) do {} while (false) | |
| 154 | |
| 155 #define ASSERT_ARGCHECK(name) do {} while (false) | |
| 156 #endif | |
| 157 | |
| 158 | |
| 159 | |
| 156 void JumpTarget::Branch(Condition cc, Result* arg, Hint hint) { | 160 void JumpTarget::Branch(Condition cc, Result* arg, Hint hint) { |
| 157 ASSERT(cgen_ != NULL); | 161 ASSERT(cgen_ != NULL); |
| 158 ASSERT(cgen_->has_valid_frame()); | 162 ASSERT(cgen_->has_valid_frame()); |
| 159 | 163 |
| 160 #ifdef DEBUG | 164 // We want to check that non-frame registers at the call site stay in |
| 161 // We want register results at the call site to stay in the same registers | 165 // the same registers on the fall-through branch. |
| 162 // on the fall-through branch. | 166 DECLARE_ARGCHECK_VARS(arg); |
| 163 Result::Type arg_type = arg->type(); | |
| 164 Register arg_reg = arg->is_register() ? arg->reg() : no_reg; | |
| 165 #endif | |
| 166 | 167 |
| 167 cgen_->frame()->Push(arg); | 168 cgen_->frame()->Push(arg); |
| 168 Branch(cc, hint); | 169 Branch(cc, hint); |
| 169 *arg = cgen_->frame()->Pop(); | 170 *arg = cgen_->frame()->Pop(); |
| 170 | 171 |
| 171 ASSERT(arg->type() == arg_type); | 172 ASSERT_ARGCHECK(arg); |
| 172 ASSERT(!arg->is_register() || arg->reg().is(arg_reg)); | |
| 173 } | 173 } |
| 174 | 174 |
| 175 | 175 |
| 176 void JumpTarget::Branch(Condition cc, Result* arg0, Result* arg1, Hint hint) { | 176 void JumpTarget::Branch(Condition cc, Result* arg0, Result* arg1, Hint hint) { |
| 177 ASSERT(cgen_ != NULL); | 177 ASSERT(cgen_ != NULL); |
| 178 ASSERT(cgen_->frame() != NULL); | 178 ASSERT(cgen_->frame() != NULL); |
| 179 | 179 |
| 180 #ifdef DEBUG | 180 // We want to check that non-frame registers at the call site stay in |
| 181 // We want register results at the call site to stay in the same registers | 181 // the same registers on the fall-through branch. |
| 182 // on the fall-through branch. | 182 DECLARE_ARGCHECK_VARS(arg0); |
| 183 Result::Type arg0_type = arg0->type(); | 183 DECLARE_ARGCHECK_VARS(arg1); |
| 184 Register arg0_reg = arg0->is_register() ? arg0->reg() : no_reg; | |
| 185 Result::Type arg1_type = arg1->type(); | |
| 186 Register arg1_reg = arg1->is_register() ? arg1->reg() : no_reg; | |
| 187 #endif | |
| 188 | 184 |
| 189 cgen_->frame()->Push(arg0); | 185 cgen_->frame()->Push(arg0); |
| 190 cgen_->frame()->Push(arg1); | 186 cgen_->frame()->Push(arg1); |
| 191 Branch(cc, hint); | 187 Branch(cc, hint); |
| 192 *arg1 = cgen_->frame()->Pop(); | 188 *arg1 = cgen_->frame()->Pop(); |
| 193 *arg0 = cgen_->frame()->Pop(); | 189 *arg0 = cgen_->frame()->Pop(); |
| 194 | 190 |
| 195 ASSERT(arg0->type() == arg0_type); | 191 ASSERT_ARGCHECK(arg0); |
| 196 ASSERT(!arg0->is_register() || arg0->reg().is(arg0_reg)); | 192 ASSERT_ARGCHECK(arg1); |
| 197 ASSERT(arg1->type() == arg1_type); | |
| 198 ASSERT(!arg1->is_register() || arg1->reg().is(arg1_reg)); | |
| 199 } | 193 } |
| 200 | 194 |
| 195 #undef DECLARE_ARGCHECK_VARS | |
| 196 #undef ASSERT_ARGCHECK | |
| 197 | |
| 201 | 198 |
| 202 void JumpTarget::Call() { | 199 void JumpTarget::Call() { |
| 203 // Precondition: there is a current frame, and there is no expected frame | 200 // Call is used to push the address of the catch block on the stack as |
| 204 // at the label. | 201 // a return address when compiling try/catch and try/finally. We |
| 202 // fully spill the frame before making the call. The expected frame | |
| 203 // at the label (which should be the only one) is the spilled current | |
| 204 // frame plus an in-memory return address. The "fall-through" frame | |
| 205 // at the return site is the spilled current frame. | |
| 205 ASSERT(cgen_ != NULL); | 206 ASSERT(cgen_ != NULL); |
| 206 ASSERT(masm_ != NULL); | 207 ASSERT(cgen_->has_valid_frame()); |
| 207 ASSERT(!cgen_->has_cc()); | 208 ASSERT(!cgen_->has_cc()); |
| 209 // There are no non-frame references across the call. | |
| 210 ASSERT(cgen_->HasValidEntryRegisters()); | |
| 211 ASSERT(!is_linked()); | |
| 208 | 212 |
| 209 VirtualFrame* current_frame = cgen_->frame(); | 213 cgen_->frame()->SpillAll(); |
| 210 ASSERT(current_frame != NULL); | 214 VirtualFrame* target_frame = new VirtualFrame(cgen_->frame()); |
| 211 ASSERT(expected_frame_ == NULL); | 215 target_frame->Adjust(1); |
| 212 ASSERT(cgen_->HasValidEntryRegisters()); | 216 AddReachingFrame(target_frame); |
| 213 | 217 __ call(&merge_labels_.last()); |
| 214 expected_frame_ = new VirtualFrame(current_frame); | |
| 215 expected_frame_->MakeMergable(); | |
| 216 // Adjust the expected frame's height to account for the return address | |
| 217 // pushed by the call instruction. | |
| 218 expected_frame_->Adjust(1); | |
| 219 ASSERT(cgen_->HasValidEntryRegisters()); | |
| 220 | |
| 221 __ call(&label_); | |
| 222 // Postcondition: there is both a current frame and an expected frame at | |
| 223 // the label. The current frame is one shorter than the one at the label | |
| 224 // (which contains the return address in memory). | |
| 225 } | 218 } |
| 226 | 219 |
| 227 | 220 |
| 228 void JumpTarget::Bind() { | 221 void JumpTarget::Bind() { |
| 229 // Precondition: there is either a current frame or an expected frame at | |
| 230 // the label (and possibly both). The label is unbound. | |
| 231 ASSERT(cgen_ != NULL); | 222 ASSERT(cgen_ != NULL); |
| 232 ASSERT(masm_ != NULL); | 223 ASSERT(is_linked() || cgen_->has_valid_frame()); |
| 224 ASSERT(!cgen_->has_cc()); | |
| 225 ASSERT(!is_bound()); | |
| 233 ASSERT(!cgen_->has_cc()); | 226 ASSERT(!cgen_->has_cc()); |
| 234 | 227 |
| 235 VirtualFrame* current_frame = cgen_->frame(); | 228 if (is_linked()) { |
| 236 ASSERT(current_frame != NULL || expected_frame_ != NULL); | 229 // There were forward jumps. A mergable frame is created and all |
| 237 ASSERT(!label_.is_bound()); | 230 // the frames reaching the block via forward jumps are merged to it. |
| 231 ASSERT(reaching_frames_.length() == merge_labels_.length()); | |
| 238 | 232 |
| 239 if (expected_frame_ == NULL) { | 233 // Choose a frame as the basis of the expected frame, and make it |
| 234 // mergable. If there is a current frame use it, otherwise use the | |
| 235 // first in the list (there will be at least one). | |
| 236 int start_index = 0; | |
| 237 if (cgen_->has_valid_frame()) { | |
| 238 // Live non-frame registers are not allowed at the start of a labeled | |
| 239 // basic block. | |
| 240 ASSERT(cgen_->HasValidEntryRegisters()); | |
| 241 } else { | |
| 242 RegisterFile reserved_registers = RegisterAllocator::Reserved(); | |
| 243 cgen_->SetFrame(reaching_frames_[start_index], &reserved_registers); | |
| 244 __ bind(&merge_labels_[start_index++]); | |
| 245 } | |
| 246 cgen_->frame()->MakeMergable(); | |
| 247 expected_frame_ = new VirtualFrame(cgen_->frame()); | |
| 248 | |
| 249 for (int i = start_index; i < reaching_frames_.length(); i++) { | |
| 250 cgen_->DeleteFrame(); | |
| 251 __ jmp(&entry_label_); | |
| 252 | |
| 253 RegisterFile reserved_registers = RegisterAllocator::Reserved(); | |
| 254 cgen_->SetFrame(reaching_frames_[i], &reserved_registers); | |
| 255 __ bind(&merge_labels_[i]); | |
| 256 | |
| 257 cgen_->frame()->MergeTo(expected_frame_); | |
| 258 } | |
| 259 __ bind(&entry_label_); | |
| 260 | |
| 261 // All but the last reaching virtual frame have been deleted, and | |
| 262 // the last one is the current frame. | |
| 263 reaching_frames_.Clear(); | |
| 264 merge_labels_.Clear(); | |
| 265 } else { | |
| 266 // There were no forward jumps. There must be a current frame, | |
| 267 // which is made mergable and used as the expected frame. | |
| 240 ASSERT(cgen_->HasValidEntryRegisters()); | 268 ASSERT(cgen_->HasValidEntryRegisters()); |
| 241 // When a label is bound the current frame becomes the expected frame at | 269 cgen_->frame()->MakeMergable(); |
| 242 // the label. This requires the current frame to be mergable. | 270 expected_frame_ = new VirtualFrame(cgen_->frame()); |
| 243 current_frame->MakeMergable(); | 271 __ bind(&entry_label_); |
| 244 ASSERT(cgen_->HasValidEntryRegisters()); | |
| 245 expected_frame_ = new VirtualFrame(current_frame); | |
| 246 } else if (current_frame == NULL) { | |
| 247 // Pick up the frame from the label. No merge code is necessary. | |
| 248 // Manually setting the reserved register reference counts is clumsy but | |
| 249 // temporary. | |
| 250 RegisterFile non_frame_registers; | |
| 251 non_frame_registers.Use(esi); | |
| 252 non_frame_registers.Use(ebp); | |
| 253 non_frame_registers.Use(esp); | |
| 254 cgen_->SetFrame(new VirtualFrame(expected_frame_), &non_frame_registers); | |
| 255 ASSERT(cgen_->HasValidEntryRegisters()); | |
| 256 } else { | |
| 257 ASSERT(cgen_->HasValidEntryRegisters()); | |
| 258 current_frame->MergeTo(expected_frame_); | |
| 259 ASSERT(cgen_->HasValidEntryRegisters()); | |
| 260 } | 272 } |
| 261 | |
| 262 __ bind(&label_); | |
| 263 // Postcondition: there is both a current frame and an expected frame at | |
| 264 // the label and they match. The label is bound. | |
| 265 } | 273 } |
| 266 | 274 |
| 267 | 275 |
| 268 void JumpTarget::Bind(Result* arg) { | 276 void JumpTarget::Bind(Result* arg) { |
| 269 ASSERT(cgen_ != NULL); | 277 ASSERT(cgen_ != NULL); |
| 270 | 278 |
| 271 if (cgen_->has_valid_frame()) { | 279 if (cgen_->has_valid_frame()) { |
| 272 cgen_->frame()->Push(arg); | 280 cgen_->frame()->Push(arg); |
| 273 } | 281 } |
| 274 Bind(); | 282 Bind(); |
| 275 *arg = cgen_->frame()->Pop(); | 283 *arg = cgen_->frame()->Pop(); |
| 276 } | 284 } |
| 277 | 285 |
| 278 | 286 |
| 279 void JumpTarget::Bind(Result* arg0, Result* arg1) { | 287 void JumpTarget::Bind(Result* arg0, Result* arg1) { |
| 280 ASSERT(cgen_ != NULL); | 288 ASSERT(cgen_ != NULL); |
| 281 | 289 |
| 282 if (cgen_->frame() != NULL) { | 290 if (cgen_->has_valid_frame()) { |
| 283 cgen_->frame()->Push(arg0); | 291 cgen_->frame()->Push(arg0); |
| 284 cgen_->frame()->Push(arg1); | 292 cgen_->frame()->Push(arg1); |
| 285 } | 293 } |
| 286 Bind(); | 294 Bind(); |
| 287 *arg1 = cgen_->frame()->Pop(); | 295 *arg1 = cgen_->frame()->Pop(); |
| 288 *arg0 = cgen_->frame()->Pop(); | 296 *arg0 = cgen_->frame()->Pop(); |
| 289 } | 297 } |
| 290 | 298 |
| 291 | 299 |
| 300 void JumpTarget::CopyTo(JumpTarget* destination) { | |
| 301 ASSERT(destination != NULL); | |
| 302 destination->cgen_ = cgen_; | |
| 303 destination->masm_ = masm_; | |
| 304 | |
| 305 destination->reaching_frames_.Clear(); | |
| 306 destination->merge_labels_.Clear(); | |
| 307 ASSERT(reaching_frames_.length() == merge_labels_.length()); | |
| 308 for (int i = 0; i < reaching_frames_.length(); i++) { | |
| 309 destination->reaching_frames_.Add(reaching_frames_[i]); | |
| 310 destination->merge_labels_.Add(merge_labels_[i]); | |
| 311 } | |
| 312 destination->expected_frame_ = expected_frame_; | |
| 313 destination->entry_label_ = entry_label_; | |
| 314 } | |
| 315 | |
| 316 | |
| 292 // ------------------------------------------------------------------------- | 317 // ------------------------------------------------------------------------- |
| 293 // ShadowTarget implementation. | 318 // ShadowTarget implementation. |
| 294 | 319 |
| 295 ShadowTarget::ShadowTarget(JumpTarget* original) { | 320 ShadowTarget::ShadowTarget(JumpTarget* shadowed) { |
| 296 ASSERT(original != NULL); | 321 ASSERT(shadowed != NULL); |
| 297 original_target_ = original; | 322 other_target_ = shadowed; |
| 298 original_pos_ = original->label()->pos_; | |
| 299 original_expected_frame_ = original->expected_frame(); | |
| 300 | 323 |
| 301 // We do not call Unuse() on the orginal jump target, because we do not | |
| 302 // want to delete the expected frame. | |
| 303 original->label()->pos_ = 0; | |
| 304 original->set_expected_frame(NULL); | |
| 305 #ifdef DEBUG | 324 #ifdef DEBUG |
| 306 is_shadowing_ = true; | 325 is_shadowing_ = true; |
| 307 #endif | 326 #endif |
| 327 // While shadowing this shadow target saves the state of the original. | |
| 328 shadowed->CopyTo(this); | |
| 329 | |
| 330 // Setting the code generator to null prevents the shadow target from | |
| 331 // being used until shadowing stops. | |
| 332 cgen_ = NULL; | |
| 333 masm_ = NULL; | |
| 334 | |
| 335 // The original's state is reset. We do not Unuse it because that | |
| 336 // would delete the expected frame and assert that the target is not | |
| 337 // linked. | |
| 338 shadowed->Reset(); | |
| 308 } | 339 } |
| 309 | 340 |
| 310 | 341 |
| 311 void ShadowTarget::StopShadowing() { | 342 void ShadowTarget::StopShadowing() { |
| 312 ASSERT(is_shadowing_); | 343 ASSERT(is_shadowing_); |
| 313 ASSERT(is_unused()); | |
| 314 | 344 |
| 315 set_code_generator(original_target_->code_generator()); | 345 // The states of this target, which was shadowed, and the original |
| 316 label_.pos_ = original_target_->label()->pos_; | 346 // target, which was shadowing, are swapped. |
| 317 expected_frame_ = original_target_->expected_frame(); | 347 JumpTarget temp; |
| 318 | 348 |
| 319 original_target_->label()->pos_ = original_pos_; | 349 other_target_->CopyTo(&temp); |
| 320 original_target_->set_expected_frame(original_expected_frame_); | 350 CopyTo(other_target_); |
| 351 temp.CopyTo(this); | |
| 352 temp.Reset(); // So the destructor does not deallocate virtual frames. | |
| 321 | 353 |
| 354 // The shadowing target does not have a valid code generator yet. | |
| 355 other_target_->set_code_generator(cgen_); | |
| 322 #ifdef DEBUG | 356 #ifdef DEBUG |
| 323 is_shadowing_ = false; | 357 is_shadowing_ = false; |
| 324 #endif | 358 #endif |
| 325 } | 359 } |
| 326 | 360 |
| 327 #undef __ | 361 #undef __ |
| 328 | 362 |
| 329 | 363 |
| 330 } } // namespace v8::internal | 364 } } // namespace v8::internal |
| OLD | NEW |