Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(341)

Side by Side Diff: src/jump-target-arm.cc

Issue 20218: A bunch of changes to get the ARM port compiling again. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/codegen-arm.cc ('k') | src/register-allocator.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 19 matching lines...) Expand all
30 #include "codegen.h" 30 #include "codegen.h"
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, Directionality direction)
41 : expected_frame_(NULL), 41 : cgen_(cgen),
42 code_generator_(cgen), 42 direction_(direction),
43 masm_(cgen->masm()) { 43 reaching_frames_(0),
44 merge_labels_(0),
45 expected_frame_(NULL),
46 is_bound_(false),
47 is_linked_(false) {
48 ASSERT(cgen_ != NULL);
49 masm_ = cgen_->masm();
44 } 50 }
45 51
46 52
47 JumpTarget::JumpTarget() 53 JumpTarget::JumpTarget()
48 : expected_frame_(NULL), 54 : cgen_(NULL),
49 code_generator_(NULL), 55 masm_(NULL),
50 masm_(NULL) { 56 direction_(FORWARD_ONLY),
51 } 57 reaching_frames_(0),
52 58 merge_labels_(0),
53 59 expected_frame_(NULL),
54 void JumpTarget::set_code_generator(CodeGenerator* cgen) { 60 is_bound_(false),
61 is_linked_(false) {
62 }
63
64
65 void JumpTarget::Initialize(CodeGenerator* cgen, Directionality direction) {
55 ASSERT(cgen != NULL); 66 ASSERT(cgen != NULL);
56 ASSERT(code_generator_ == NULL); 67 ASSERT(cgen_ == NULL);
57 code_generator_ = cgen; 68 cgen_ = cgen;
58 masm_ = cgen->masm(); 69 masm_ = cgen->masm();
70 direction_ = direction;
71 }
72
73
74 void JumpTarget::Unuse() {
75 ASSERT(!is_linked());
76 entry_label_.Unuse();
77 delete expected_frame_;
78 expected_frame_ = NULL;
79 is_bound_ = false;
80 is_linked_ = false;
81 }
82
83
84 void JumpTarget::Reset() {
85 reaching_frames_.Clear();
86 merge_labels_.Clear();
87 expected_frame_ = NULL;
88 entry_label_.Unuse();
89 is_bound_ = false;
90 is_linked_ = false;
59 } 91 }
60 92
61 93
62 void JumpTarget::Jump() { 94 void JumpTarget::Jump() {
63 // Precondition: there is a current frame. There may or may not be an 95 ASSERT(cgen_ != NULL);
64 // expected frame at the label. 96 ASSERT(cgen_->has_valid_frame());
65 ASSERT(code_generator_ != NULL); 97 // Live non-frame registers are not allowed at unconditional jumps
66 98 // because we have no way of invalidating the corresponding results
67 VirtualFrame* current_frame = code_generator_->frame(); 99 // which are still live in the C++ code.
68 ASSERT(current_frame != NULL); 100 ASSERT(cgen_->HasValidEntryRegisters());
69 101
70 if (expected_frame_ == NULL) { 102 if (is_bound()) {
71 expected_frame_ = current_frame; 103 // Backward jump. There is an expected frame to merge to.
72 code_generator_->set_frame(NULL); 104 ASSERT(direction_ == BIDIRECTIONAL);
73 // The frame at the actual function return will always have height zero. 105 cgen_->frame()->MergeTo(expected_frame_);
74 if (code_generator_->IsActualFunctionReturn(this)) { 106 cgen_->DeleteFrame();
75 expected_frame_->Forget(expected_frame_->height()); 107 __ jmp(&entry_label_);
108 } else {
109 // Forward jump. The current frame is added to the end of the list
110 // of frames reaching the target block and a jump to the merge code
111 // is emitted.
112 AddReachingFrame(cgen_->frame());
113 cgen_->SetFrame(NULL);
114 __ jmp(&merge_labels_.last());
115 }
116
117 is_linked_ = !is_bound_;
118 }
119
120
121 void JumpTarget::Jump(Result* arg) {
122 UNIMPLEMENTED();
123 }
124
125
126 void JumpTarget::Jump(Result* arg0, Result* arg1) {
127 UNIMPLEMENTED();
128 }
129
130
131 void JumpTarget::Jump(Result* arg0, Result* arg1, Result* arg2) {
132 UNIMPLEMENTED();
133 }
134
135
136 void JumpTarget::Branch(Condition cc, Hint ignored) {
137 ASSERT(cgen_ != NULL);
138 ASSERT(cgen_->has_valid_frame());
139
140 if (is_bound()) {
141 // Backward branch. We have an expected frame to merge to on the
142 // backward edge. We negate the condition and emit the merge code
143 // here.
144 //
145 // TODO(210): we should try to avoid negating the condition in the
146 // case where there is no merge code to emit. Otherwise, we emit
147 // a branch around an unconditional jump.
148 ASSERT(direction_ == BIDIRECTIONAL);
149 Label original_fall_through;
150 __ b(NegateCondition(cc), &original_fall_through);
151 // Swap the current frame for a copy of it, saving non-frame
152 // register reference counts and invalidating all non-frame register
153 // references except the reserved ones on the backward edge.
154 VirtualFrame* original_frame = cgen_->frame();
155 VirtualFrame* working_frame = new VirtualFrame(original_frame);
156 cgen_->SetFrame(working_frame);
157
158 working_frame->MergeTo(expected_frame_);
159 cgen_->DeleteFrame();
160 __ jmp(&entry_label_);
161
162 // Restore the frame and its associated non-frame registers.
163 cgen_->SetFrame(original_frame);
164 __ bind(&original_fall_through);
165 } else {
166 // Forward branch. A copy of the current frame is added to the end
167 // of the list of frames reaching the target block and a branch to
168 // the merge code is emitted.
169 AddReachingFrame(new VirtualFrame(cgen_->frame()));
170 __ b(cc, &merge_labels_.last());
171 }
172
173 is_linked_ = !is_bound_;
174 }
175
176
177 void JumpTarget::Branch(Condition cc, Result* arg, Hint ignored) {
178 UNIMPLEMENTED();
179 }
180
181
182 void JumpTarget::Branch(Condition cc,
183 Result* arg0,
184 Result* arg1,
185 Hint ignored) {
186 UNIMPLEMENTED();
187 }
188
189
190 void JumpTarget::Branch(Condition cc,
191 Result* arg0,
192 Result* arg1,
193 Result* arg2,
194 Hint ignored) {
195 UNIMPLEMENTED();
196 }
197
198
199 void JumpTarget::Branch(Condition cc,
200 Result* arg0,
201 Result* arg1,
202 Result* arg2,
203 Result* arg3,
204 Hint ignored) {
205 UNIMPLEMENTED();
206 }
207
208
209 void JumpTarget::Call() {
210 // Call is used to push the address of the catch block on the stack as
211 // a return address when compiling try/catch and try/finally. We
212 // fully spill the frame before making the call. The expected frame
213 // at the label (which should be the only one) is the spilled current
214 // frame plus an in-memory return address. The "fall-through" frame
215 // at the return site is the spilled current frame.
216 ASSERT(cgen_ != NULL);
217 ASSERT(cgen_->has_valid_frame());
218 // There are no non-frame references across the call.
219 ASSERT(cgen_->HasValidEntryRegisters());
220 ASSERT(!is_linked());
221
222 VirtualFrame* target_frame = new VirtualFrame(cgen_->frame());
223 target_frame->Adjust(1);
224 AddReachingFrame(target_frame);
225 __ bl(&merge_labels_.last());
226
227 is_linked_ = !is_bound_;
228 }
229
230
231 void JumpTarget::Bind() {
232 ASSERT(cgen_ != NULL);
233 ASSERT(!is_bound());
234
235 if (is_linked()) {
236 // There were forward jumps. A mergable frame is created and all
237 // the frames reaching the block via forward jumps are merged to it.
238 ASSERT(reaching_frames_.length() == merge_labels_.length());
239
240 // A special case is that there was only one jump to the block so
241 // far, no fall-through, and there cannot be another entry because
242 // the block is forward only. In that case, simply use the single
243 // frame.
244 bool single_entry = (direction_ == FORWARD_ONLY) &&
245 !cgen_->has_valid_frame() &&
246 (reaching_frames_.length() == 1);
247 if (single_entry) {
248 // Pick up the only forward reaching frame and bind its merge
249 // label. No merge code is emitted.
250 cgen_->SetFrame(reaching_frames_[0]);
251 __ bind(&merge_labels_[0]);
252 } else {
253 // Otherwise, choose a frame as the basis of the expected frame,
254 // and make it mergable. If there is a current frame use it,
255 // otherwise use the first in the list (there will be at least
256 // one).
257 int start_index = 0;
258 if (cgen_->has_valid_frame()) {
259 // Live non-frame registers are not allowed at the start of a
260 // labeled basic block.
261 ASSERT(cgen_->HasValidEntryRegisters());
262 } else {
263 cgen_->SetFrame(reaching_frames_[start_index]);
264 __ bind(&merge_labels_[start_index++]);
265 }
266 cgen_->frame()->MakeMergable();
267 expected_frame_ = new VirtualFrame(cgen_->frame());
268
269 for (int i = start_index; i < reaching_frames_.length(); i++) {
270 cgen_->DeleteFrame();
271 __ jmp(&entry_label_);
272
273 cgen_->SetFrame(reaching_frames_[i]);
274 __ bind(&merge_labels_[i]);
275
276 cgen_->frame()->MergeTo(expected_frame_);
277 }
278
279 __ bind(&entry_label_);
76 } 280 }
281
282 // All but the last reaching virtual frame have been deleted, and
283 // the last one is the current frame.
284 reaching_frames_.Clear();
285 merge_labels_.Clear();
286
77 } else { 287 } else {
78 // No code needs to be emitted to merge to the expected frame at the 288 // There were no forward jumps. If this jump target is not
79 // actual function return. 289 // bidirectional, there is no need to do anything. For
80 if (!code_generator_->IsActualFunctionReturn(this)) { 290 // bidirectional jump targets, the current frame is made mergable
81 current_frame->MergeTo(expected_frame_); 291 // and used for the expected frame.
82 } 292 if (direction_ == BIDIRECTIONAL) {
83 code_generator_->delete_frame(); 293 ASSERT(cgen_->HasValidEntryRegisters());
84 } 294 cgen_->frame()->MakeMergable();
85 295 expected_frame_ = new VirtualFrame(cgen_->frame());
86 __ b(&label_); 296 __ bind(&entry_label_);
87 // Postcondition: there is no current frame but there is an expected frame
88 // at the label.
89 }
90
91
92 void JumpTarget::Branch(Condition cc, Hint ignored) {
93 // Precondition: there is a current frame. There may or may not be an
94 // expected frame at the label.
95 ASSERT(code_generator_ != NULL);
96 ASSERT(masm_ != NULL);
97
98 VirtualFrame* current_frame = code_generator_->frame();
99 ASSERT(current_frame != NULL);
100
101 if (expected_frame_ == NULL) {
102 expected_frame_ = new VirtualFrame(current_frame);
103 // The frame at the actual function return will always have height zero.
104 if (code_generator_->IsActualFunctionReturn(this)) {
105 expected_frame_->Forget(expected_frame_->height());
106 }
107 } else {
108 // No code needs to be emitted to merge to the expected frame at the
109 // actual function return.
110 if (!code_generator_->IsActualFunctionReturn(this)) {
111 current_frame->MergeTo(expected_frame_);
112 } 297 }
113 } 298 }
114 299
115 __ b(cc, &label_); 300 is_linked_ = false;
116 // Postcondition: there is both a current frame and an expected frame at 301 is_bound_ = true;
117 // the label and they match. 302 }
118 } 303
119 304
120 305 void JumpTarget::Bind(Result* arg) {
121 void JumpTarget::Call() { 306 UNIMPLEMENTED();
122 // Precondition: there is a current frame, and there is no expected frame 307 }
123 // at the label. 308
124 ASSERT(code_generator_ != NULL); 309
125 ASSERT(masm_ != NULL); 310 void JumpTarget::Bind(Result* arg0, Result* arg1) {
126 ASSERT(!code_generator_->IsActualFunctionReturn(this)); 311 UNIMPLEMENTED();
127 312 }
128 VirtualFrame* current_frame = code_generator_->frame(); 313
129 ASSERT(current_frame != NULL); 314
130 ASSERT(expected_frame_ == NULL); 315 void JumpTarget::Bind(Result* arg0, Result* arg1, Result* arg2) {
131 316 UNIMPLEMENTED();
132 expected_frame_ = new VirtualFrame(current_frame); 317 }
133 // Adjust the expected frame's height to account for the return address 318
134 // pushed by the call instruction. 319
135 expected_frame_->Adjust(1); 320 void JumpTarget::Bind(Result* arg0, Result* arg1, Result* arg2, Result* arg3) {
136 321 UNIMPLEMENTED();
137 __ bl(&label_); 322 }
138 // Postcondition: there is both a current frame and an expected frame at 323
139 // the label. The current frame is one shorter than the one at the label 324
140 // (which contains the return address in memory). 325 void JumpTarget::CopyTo(JumpTarget* destination) {
141 } 326 ASSERT(destination != NULL);
142 327 destination->cgen_ = cgen_;
143 328 destination->masm_ = masm_;
144 void JumpTarget::Bind() { 329 destination->direction_ = direction_;
145 // Precondition: there is either a current frame or an expected frame at 330 destination->reaching_frames_.Clear();
146 // the label (and possibly both). The label is unbound. 331 destination->merge_labels_.Clear();
147 ASSERT(code_generator_ != NULL); 332 ASSERT(reaching_frames_.length() == merge_labels_.length());
148 ASSERT(masm_ != NULL); 333 for (int i = 0; i < reaching_frames_.length(); i++) {
149 334 destination->reaching_frames_.Add(reaching_frames_[i]);
150 VirtualFrame* current_frame = code_generator_->frame(); 335 destination->merge_labels_.Add(merge_labels_[i]);
151 ASSERT(current_frame != NULL || expected_frame_ != NULL);
152 ASSERT(!label_.is_bound());
153
154 if (expected_frame_ == NULL) {
155 expected_frame_ = new VirtualFrame(current_frame);
156 // The frame at the actual function return will always have height zero.
157 if (code_generator_->IsActualFunctionReturn(this)) {
158 expected_frame_->Forget(expected_frame_->height());
159 }
160 } else if (current_frame == NULL) {
161 code_generator_->set_frame(new VirtualFrame(expected_frame_));
162 } else {
163 // No code needs to be emitted to merge to the expected frame at the
164 // actual function return.
165 if (!code_generator_->IsActualFunctionReturn(this)) {
166 current_frame->MergeTo(expected_frame_);
167 }
168 } 336 }
169 337 destination->expected_frame_ = expected_frame_;
170 __ bind(&label_); 338 destination->entry_label_ = entry_label_;
171 // Postcondition: there is both a current frame and an expected frame at 339 destination->is_bound_ = is_bound_;
172 // the label and they match. The label is bound. 340 destination->is_linked_ = is_linked_;
341 }
342
343
344 void JumpTarget::AddReachingFrame(VirtualFrame* frame) {
345 ASSERT(reaching_frames_.length() == merge_labels_.length());
346 Label fresh;
347 merge_labels_.Add(fresh);
348 reaching_frames_.Add(frame);
173 } 349 }
174 350
175 351
176 // ------------------------------------------------------------------------- 352 // -------------------------------------------------------------------------
177 // ShadowTarget implementation. 353 // ShadowTarget implementation.
178 354
179 ShadowTarget::ShadowTarget(JumpTarget* original) { 355 ShadowTarget::ShadowTarget(JumpTarget* shadowed) {
180 ASSERT(original != NULL); 356 ASSERT(shadowed != NULL);
181 original_target_ = original; 357 other_target_ = shadowed;
182 original_pos_ = original->label()->pos_; 358
183 original_expected_frame_ = original->expected_frame();
184
185 // We do not call Unuse() on the orginal jump target, because we do not
186 // want to delete the expected frame.
187 original->label()->pos_ = 0;
188 original->set_expected_frame(NULL);
189 #ifdef DEBUG 359 #ifdef DEBUG
190 is_shadowing_ = true; 360 is_shadowing_ = true;
191 #endif 361 #endif
362 // While shadowing this shadow target saves the state of the original.
363 shadowed->CopyTo(this);
364
365 // Setting the code generator to null prevents the shadow target from
366 // being used until shadowing stops.
367 cgen_ = NULL;
368 masm_ = NULL;
369
370 // The original's state is reset. We do not Unuse it because that
371 // would delete the expected frame and assert that the target is not
372 // linked.
373 shadowed->Reset();
192 } 374 }
193 375
194 376
195 void ShadowTarget::StopShadowing() { 377 void ShadowTarget::StopShadowing() {
196 ASSERT(is_shadowing_); 378 ASSERT(is_shadowing_);
197 ASSERT(is_unused()); 379
198 380 // This target does not have a valid code generator yet.
199 set_code_generator(original_target_->code_generator()); 381 cgen_ = other_target_->code_generator();
200 label_.pos_ = original_target_->label()->pos_; 382 ASSERT(cgen_ != NULL);
201 expected_frame_ = original_target_->expected_frame(); 383 masm_ = cgen_->masm();
202 384
203 original_target_->label()->pos_ = original_pos_; 385 // The states of this target, which was shadowed, and the original
204 original_target_->set_expected_frame(original_expected_frame_); 386 // target, which was shadowing, are swapped.
387 JumpTarget temp;
388 other_target_->CopyTo(&temp);
389 CopyTo(other_target_);
390 temp.CopyTo(this);
391 temp.Reset(); // So the destructor does not deallocate virtual frames.
205 392
206 #ifdef DEBUG 393 #ifdef DEBUG
207 is_shadowing_ = false; 394 is_shadowing_ = false;
208 #endif 395 #endif
209 } 396 }
210 397
211 #undef __ 398 #undef __
212 399
213 400
214 } } // namespace v8::internal 401 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen-arm.cc ('k') | src/register-allocator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698