| 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 21 matching lines...) Expand all Loading... |
| 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 : expected_frame_(NULL), |
| 42 code_generator_(cgen), | 42 cgen_(cgen), |
| 43 masm_(cgen->masm()) { | 43 masm_(cgen->masm()) { |
| 44 } | 44 } |
| 45 | 45 |
| 46 | 46 |
| 47 JumpTarget::JumpTarget() | 47 JumpTarget::JumpTarget() |
| 48 : expected_frame_(NULL), | 48 : expected_frame_(NULL), |
| 49 code_generator_(NULL), | 49 cgen_(NULL), |
| 50 masm_(NULL) { | 50 masm_(NULL) { |
| 51 } | 51 } |
| 52 | 52 |
| 53 | 53 |
| 54 void JumpTarget::set_code_generator(CodeGenerator* cgen) { | 54 void JumpTarget::set_code_generator(CodeGenerator* cgen) { |
| 55 ASSERT(cgen != NULL); | 55 ASSERT(cgen != NULL); |
| 56 ASSERT(code_generator_ == NULL); | 56 ASSERT(cgen_ == NULL); |
| 57 code_generator_ = cgen; | 57 cgen_ = cgen; |
| 58 masm_ = cgen->masm(); | 58 masm_ = cgen->masm(); |
| 59 } | 59 } |
| 60 | 60 |
| 61 | 61 |
| 62 void JumpTarget::Jump() { | 62 void JumpTarget::Jump() { |
| 63 // Precondition: there is a current frame. There may or may not be an | 63 // Precondition: there is a current frame. There may or may not be an |
| 64 // expected frame at the label. | 64 // expected frame at the label. |
| 65 ASSERT(code_generator_ != NULL); | 65 ASSERT(cgen_ != NULL); |
| 66 | 66 |
| 67 VirtualFrame* current_frame = code_generator_->frame(); | 67 VirtualFrame* current_frame = cgen_->frame(); |
| 68 ASSERT(current_frame != NULL); | 68 ASSERT(current_frame != NULL); |
| 69 ASSERT(cgen_->HasValidEntryRegisters()); |
| 69 | 70 |
| 70 if (expected_frame_ == NULL) { | 71 if (expected_frame_ == NULL) { |
| 71 // The frame at the actual function return will always have height zero. | 72 // The frame at the actual function return will always have height zero. |
| 72 if (code_generator_->IsActualFunctionReturn(this)) { | 73 if (cgen_->IsActualFunctionReturn(this)) { |
| 73 current_frame->Forget(current_frame->height()); | 74 current_frame->Forget(current_frame->height()); |
| 74 } | 75 } |
| 75 if (!current_frame->IsMergable()) { | 76 current_frame->MakeMergable(); |
| 76 current_frame->MakeMergable(); | |
| 77 } | |
| 78 expected_frame_ = current_frame; | 77 expected_frame_ = current_frame; |
| 79 code_generator_->SetFrame(NULL); | 78 ASSERT(cgen_->HasValidEntryRegisters()); |
| 79 cgen_->SetFrame(NULL); |
| 80 } else { | 80 } else { |
| 81 // No code needs to be emitted to merge to the expected frame at the | 81 // No code needs to be emitted to merge to the expected frame at the |
| 82 // actual function return. | 82 // actual function return. |
| 83 if (!code_generator_->IsActualFunctionReturn(this)) { | 83 if (!cgen_->IsActualFunctionReturn(this)) { |
| 84 current_frame->MergeTo(expected_frame_); | 84 current_frame->MergeTo(expected_frame_); |
| 85 } | 85 } |
| 86 code_generator_->DeleteFrame(); | 86 ASSERT(cgen_->HasValidEntryRegisters()); |
| 87 cgen_->DeleteFrame(); |
| 87 } | 88 } |
| 88 | 89 |
| 89 __ jmp(&label_); | 90 __ jmp(&label_); |
| 90 // Postcondition: there is no current frame but there is an expected frame | 91 // Postcondition: there is no current frame but there is an expected frame |
| 91 // at the label. | 92 // at the label. |
| 92 } | 93 } |
| 93 | 94 |
| 94 | 95 |
| 95 void JumpTarget::Branch(Condition cc, Hint hint) { | 96 void JumpTarget::Branch(Condition cc, Hint hint) { |
| 96 // Precondition: there is a current frame. There may or may not be an | 97 // Precondition: there is a current frame. There may or may not be an |
| 97 // expected frame at the label. | 98 // expected frame at the label. |
| 98 ASSERT(code_generator_ != NULL); | 99 ASSERT(cgen_ != NULL); |
| 99 ASSERT(masm_ != NULL); | 100 ASSERT(masm_ != NULL); |
| 100 | 101 |
| 101 VirtualFrame* current_frame = code_generator_->frame(); | 102 VirtualFrame* current_frame = cgen_->frame(); |
| 102 ASSERT(current_frame != NULL); | 103 ASSERT(current_frame != NULL); |
| 104 ASSERT(cgen_->HasValidEntryRegisters()); |
| 103 | 105 |
| 104 if (expected_frame_ == NULL) { | 106 if (expected_frame_ == NULL) { |
| 105 expected_frame_ = new VirtualFrame(current_frame); | 107 expected_frame_ = new VirtualFrame(current_frame); |
| 106 // The frame at the actual function return will always have height zero. | 108 // The frame at the actual function return will always have height zero. |
| 107 if (code_generator_->IsActualFunctionReturn(this)) { | 109 if (cgen_->IsActualFunctionReturn(this)) { |
| 108 expected_frame_->Forget(expected_frame_->height()); | 110 expected_frame_->Forget(expected_frame_->height()); |
| 109 } | 111 } |
| 110 // For a branch, the frame at the fall-through basic block (not labeled) | 112 // For a branch, the frame at the fall-through basic block (not labeled) |
| 111 // does not need to be mergable, but only the other (labeled) one. That | 113 // does not need to be mergable, but only the other (labeled) one. That |
| 112 // is achieved by reversing the condition and emitting the make mergable | 114 // is achieved by reversing the condition and emitting the make mergable |
| 113 // code as the actual fall-through block. This is necessary only when | 115 // code as the actual fall-through block. This is necessary only when |
| 114 // MakeMergable will generate code. | 116 // MakeMergable will generate code. |
| 115 if (expected_frame_->RequiresMergeCode()) { | 117 if (expected_frame_->RequiresMergeCode()) { |
| 116 Label original_fall_through; | 118 Label original_fall_through; |
| 117 __ j(NegateCondition(cc), &original_fall_through, NegateHint(hint)); | 119 __ j(NegateCondition(cc), &original_fall_through, NegateHint(hint)); |
| 118 expected_frame_->MakeMergable(); | 120 expected_frame_->MakeMergable(); |
| 119 __ jmp(&label_); | 121 __ jmp(&label_); |
| 120 __ bind(&original_fall_through); | 122 __ bind(&original_fall_through); |
| 121 } else { | 123 } else { |
| 122 if (!expected_frame_->IsMergable()) { | 124 expected_frame_->MakeMergable(); |
| 123 expected_frame_->MakeMergable(); | 125 ASSERT(cgen_->HasValidEntryRegisters()); |
| 124 } | |
| 125 __ j(cc, &label_, hint); | 126 __ j(cc, &label_, hint); |
| 126 } | 127 } |
| 127 } else { | 128 } else { |
| 128 // No code needs to be emitted to merge to the expected frame at the | 129 // No code needs to be emitted to merge to the expected frame at the |
| 129 // actual function return. | 130 // actual function return. |
| 130 if (!code_generator_->IsActualFunctionReturn(this)) { | 131 if (!cgen_->IsActualFunctionReturn(this)) { |
| 131 current_frame->MergeTo(expected_frame_); | 132 current_frame->MergeTo(expected_frame_); |
| 132 } | 133 } |
| 134 ASSERT(cgen_->HasValidEntryRegisters()); |
| 133 __ j(cc, &label_, hint); | 135 __ j(cc, &label_, hint); |
| 134 } | 136 } |
| 135 // Postcondition: there is both a current frame and an expected frame at | 137 // Postcondition: there is both a current frame and an expected frame at |
| 136 // the label and they match. | 138 // the label and they match. |
| 137 } | 139 } |
| 138 | 140 |
| 139 | 141 |
| 142 void JumpTarget::Branch(Condition cc, Result* arg, Hint hint) { |
| 143 ASSERT(cgen_ != NULL); |
| 144 ASSERT(cgen_->frame() != NULL); |
| 145 |
| 146 #ifdef DEBUG |
| 147 // We want register results at the call site to stay in the same registers |
| 148 // on the fall-through branch. |
| 149 Result::Type arg_type = arg->type(); |
| 150 Register arg_reg = arg->is_register() ? arg->reg() : no_reg; |
| 151 #endif |
| 152 |
| 153 cgen_->frame()->Push(arg); |
| 154 Branch(cc, hint); |
| 155 *arg = cgen_->frame()->Pop(); |
| 156 |
| 157 ASSERT(arg->type() == arg_type); |
| 158 ASSERT(!arg->is_register() || arg->reg().is(arg_reg)); |
| 159 } |
| 160 |
| 161 |
| 140 void JumpTarget::Call() { | 162 void JumpTarget::Call() { |
| 141 // Precondition: there is a current frame, and there is no expected frame | 163 // Precondition: there is a current frame, and there is no expected frame |
| 142 // at the label. | 164 // at the label. |
| 143 ASSERT(code_generator_ != NULL); | 165 ASSERT(cgen_ != NULL); |
| 144 ASSERT(masm_ != NULL); | 166 ASSERT(masm_ != NULL); |
| 145 ASSERT(!code_generator_->IsActualFunctionReturn(this)); | 167 ASSERT(!cgen_->IsActualFunctionReturn(this)); |
| 146 | 168 |
| 147 VirtualFrame* current_frame = code_generator_->frame(); | 169 VirtualFrame* current_frame = cgen_->frame(); |
| 148 ASSERT(current_frame != NULL); | 170 ASSERT(current_frame != NULL); |
| 149 ASSERT(expected_frame_ == NULL); | 171 ASSERT(expected_frame_ == NULL); |
| 172 ASSERT(cgen_->HasValidEntryRegisters()); |
| 150 | 173 |
| 151 expected_frame_ = new VirtualFrame(current_frame); | 174 expected_frame_ = new VirtualFrame(current_frame); |
| 152 if (!expected_frame_->IsMergable()) { | 175 expected_frame_->MakeMergable(); |
| 153 expected_frame_->MakeMergable(); | |
| 154 } | |
| 155 // Adjust the expected frame's height to account for the return address | 176 // Adjust the expected frame's height to account for the return address |
| 156 // pushed by the call instruction. | 177 // pushed by the call instruction. |
| 157 expected_frame_->Adjust(1); | 178 expected_frame_->Adjust(1); |
| 179 ASSERT(cgen_->HasValidEntryRegisters()); |
| 158 | 180 |
| 159 __ call(&label_); | 181 __ call(&label_); |
| 160 // Postcondition: there is both a current frame and an expected frame at | 182 // Postcondition: there is both a current frame and an expected frame at |
| 161 // the label. The current frame is one shorter than the one at the label | 183 // the label. The current frame is one shorter than the one at the label |
| 162 // (which contains the return address in memory). | 184 // (which contains the return address in memory). |
| 163 } | 185 } |
| 164 | 186 |
| 165 | 187 |
| 166 void JumpTarget::Bind() { | 188 void JumpTarget::Bind() { |
| 167 // Precondition: there is either a current frame or an expected frame at | 189 // Precondition: there is either a current frame or an expected frame at |
| 168 // the label (and possibly both). The label is unbound. | 190 // the label (and possibly both). The label is unbound. |
| 169 ASSERT(code_generator_ != NULL); | 191 ASSERT(cgen_ != NULL); |
| 170 ASSERT(masm_ != NULL); | 192 ASSERT(masm_ != NULL); |
| 171 | 193 |
| 172 VirtualFrame* current_frame = code_generator_->frame(); | 194 VirtualFrame* current_frame = cgen_->frame(); |
| 173 ASSERT(current_frame != NULL || expected_frame_ != NULL); | 195 ASSERT(current_frame != NULL || expected_frame_ != NULL); |
| 174 ASSERT(!label_.is_bound()); | 196 ASSERT(!label_.is_bound()); |
| 175 | 197 |
| 176 if (expected_frame_ == NULL) { | 198 if (expected_frame_ == NULL) { |
| 199 ASSERT(cgen_->HasValidEntryRegisters()); |
| 177 // When a label is bound the current frame becomes the expected frame at | 200 // When a label is bound the current frame becomes the expected frame at |
| 178 // the label. This requires the current frame to be mergable. | 201 // the label. This requires the current frame to be mergable. |
| 179 // The frame at the actual function return will always have height zero. | 202 // The frame at the actual function return will always have height zero. |
| 180 if (code_generator_->IsActualFunctionReturn(this)) { | 203 if (cgen_->IsActualFunctionReturn(this)) { |
| 181 current_frame->Forget(current_frame->height()); | 204 current_frame->Forget(current_frame->height()); |
| 182 } | 205 } |
| 183 if (!current_frame->IsMergable()) { | 206 current_frame->MakeMergable(); |
| 184 current_frame->MakeMergable(); | 207 ASSERT(cgen_->HasValidEntryRegisters()); |
| 185 } | |
| 186 expected_frame_ = new VirtualFrame(current_frame); | 208 expected_frame_ = new VirtualFrame(current_frame); |
| 187 } else if (current_frame == NULL) { | 209 } else if (current_frame == NULL) { |
| 188 code_generator_->SetFrame(new VirtualFrame(expected_frame_)); | 210 cgen_->SetFrame(new VirtualFrame(expected_frame_)); |
| 211 ASSERT(cgen_->HasValidEntryRegisters()); |
| 189 } else { | 212 } else { |
| 213 ASSERT(cgen_->HasValidEntryRegisters()); |
| 190 // No code needs to be emitted to merge to the expected frame at the | 214 // No code needs to be emitted to merge to the expected frame at the |
| 191 // actual function return. | 215 // actual function return. |
| 192 if (!code_generator_->IsActualFunctionReturn(this)) { | 216 if (!cgen_->IsActualFunctionReturn(this)) { |
| 193 current_frame->MergeTo(expected_frame_); | 217 current_frame->MergeTo(expected_frame_); |
| 194 } | 218 } |
| 219 ASSERT(cgen_->HasValidEntryRegisters()); |
| 195 } | 220 } |
| 196 | 221 |
| 197 __ bind(&label_); | 222 __ bind(&label_); |
| 198 // Postcondition: there is both a current frame and an expected frame at | 223 // Postcondition: there is both a current frame and an expected frame at |
| 199 // the label and they match. The label is bound. | 224 // the label and they match. The label is bound. |
| 200 } | 225 } |
| 201 | 226 |
| 202 | 227 |
| 228 void JumpTarget::Bind(Result* arg) { |
| 229 ASSERT(cgen_ != NULL); |
| 230 |
| 231 #ifdef DEBUG |
| 232 // We want register results at the call site to stay in the same |
| 233 // registers. |
| 234 bool had_entry_frame = false; |
| 235 Result::Type arg_type; |
| 236 Register arg_reg; |
| 237 #endif |
| 238 |
| 239 if (cgen_->frame() != NULL) { |
| 240 #ifdef DEBUG |
| 241 had_entry_frame = true; |
| 242 arg_type = arg->type(); |
| 243 arg_reg = arg->is_register() ? arg->reg() : no_reg; |
| 244 #endif |
| 245 cgen_->frame()->Push(arg); |
| 246 } |
| 247 Bind(); |
| 248 *arg = cgen_->frame()->Pop(); |
| 249 |
| 250 ASSERT(!had_entry_frame || arg->type() == arg_type); |
| 251 ASSERT(!had_entry_frame || !arg->is_register() || arg->reg().is(arg_reg)); |
| 252 } |
| 253 |
| 254 |
| 203 // ------------------------------------------------------------------------- | 255 // ------------------------------------------------------------------------- |
| 204 // ShadowTarget implementation. | 256 // ShadowTarget implementation. |
| 205 | 257 |
| 206 ShadowTarget::ShadowTarget(JumpTarget* original) { | 258 ShadowTarget::ShadowTarget(JumpTarget* original) { |
| 207 ASSERT(original != NULL); | 259 ASSERT(original != NULL); |
| 208 original_target_ = original; | 260 original_target_ = original; |
| 209 original_pos_ = original->label()->pos_; | 261 original_pos_ = original->label()->pos_; |
| 210 original_expected_frame_ = original->expected_frame(); | 262 original_expected_frame_ = original->expected_frame(); |
| 211 | 263 |
| 212 // We do not call Unuse() on the orginal jump target, because we do not | 264 // We do not call Unuse() on the orginal jump target, because we do not |
| (...skipping 19 matching lines...) Expand all Loading... |
| 232 | 284 |
| 233 #ifdef DEBUG | 285 #ifdef DEBUG |
| 234 is_shadowing_ = false; | 286 is_shadowing_ = false; |
| 235 #endif | 287 #endif |
| 236 } | 288 } |
| 237 | 289 |
| 238 #undef __ | 290 #undef __ |
| 239 | 291 |
| 240 | 292 |
| 241 } } // namespace v8::internal | 293 } } // namespace v8::internal |
| OLD | NEW |