OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 #include "register-allocator-inl.h" | 32 #include "register-allocator-inl.h" |
33 | 33 |
34 namespace v8 { namespace internal { | 34 namespace v8 { namespace internal { |
35 | 35 |
36 // ------------------------------------------------------------------------- | 36 // ------------------------------------------------------------------------- |
37 // JumpTarget implementation. | 37 // JumpTarget implementation. |
38 | 38 |
39 bool JumpTarget::compiling_deferred_code_ = false; | 39 bool JumpTarget::compiling_deferred_code_ = false; |
40 | 40 |
41 | 41 |
42 JumpTarget::JumpTarget(CodeGenerator* cgen, Directionality direction) | |
43 : cgen_(cgen), | |
44 direction_(direction), | |
45 reaching_frames_(0), | |
46 merge_labels_(0), | |
47 entry_frame_(NULL) { | |
48 ASSERT(cgen != NULL); | |
49 masm_ = cgen->masm(); | |
50 } | |
51 | |
52 | |
53 JumpTarget::JumpTarget() | |
54 : cgen_(NULL), | |
55 masm_(NULL), | |
56 direction_(FORWARD_ONLY), | |
57 reaching_frames_(0), | |
58 merge_labels_(0), | |
59 entry_frame_(NULL) { | |
60 } | |
61 | |
62 | |
63 void JumpTarget::Initialize(CodeGenerator* cgen, Directionality direction) { | |
64 ASSERT(cgen != NULL); | |
65 ASSERT(cgen_ == NULL); | |
66 cgen_ = cgen; | |
67 masm_ = cgen->masm(); | |
68 direction_ = direction; | |
69 } | |
70 | |
71 | |
72 void JumpTarget::Unuse() { | 42 void JumpTarget::Unuse() { |
73 reaching_frames_.Clear(); | 43 reaching_frames_.Clear(); |
74 merge_labels_.Clear(); | 44 merge_labels_.Clear(); |
75 entry_frame_ = NULL; | 45 entry_frame_ = NULL; |
76 entry_label_.Unuse(); | 46 entry_label_.Unuse(); |
77 } | 47 } |
78 | 48 |
79 | 49 |
80 void JumpTarget::ComputeEntryFrame(int mergable_elements) { | 50 void JumpTarget::ComputeEntryFrame(int mergable_elements) { |
81 // Given: a collection of frames reaching by forward CFG edges and | 51 // Given: a collection of frames reaching by forward CFG edges and |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 | 114 |
145 element = element->Combine(&reaching_frames_[j]->elements_[i]); | 115 element = element->Combine(&reaching_frames_[j]->elements_[i]); |
146 } | 116 } |
147 elements[i] = element; | 117 elements[i] = element; |
148 } | 118 } |
149 } | 119 } |
150 | 120 |
151 // Build the new frame. A freshly allocated frame has memory elements | 121 // Build the new frame. A freshly allocated frame has memory elements |
152 // for the parameters and some platform-dependent elements (e.g., | 122 // for the parameters and some platform-dependent elements (e.g., |
153 // return address). Replace those first. | 123 // return address). Replace those first. |
154 entry_frame_ = new VirtualFrame(cgen_); | 124 entry_frame_ = new VirtualFrame(cgen()); |
155 int index = 0; | 125 int index = 0; |
156 for (; index < entry_frame_->elements_.length(); index++) { | 126 for (; index < entry_frame_->elements_.length(); index++) { |
157 FrameElement* target = elements[index]; | 127 FrameElement* target = elements[index]; |
158 // If the element is determined, set it now. Count registers. Mark | 128 // If the element is determined, set it now. Count registers. Mark |
159 // elements as copied exactly when they have a copy. Undetermined | 129 // elements as copied exactly when they have a copy. Undetermined |
160 // elements are initially recorded as if in memory. | 130 // elements are initially recorded as if in memory. |
161 if (target != NULL) { | 131 if (target != NULL) { |
162 entry_frame_->elements_[index] = *target; | 132 entry_frame_->elements_[index] = *target; |
163 InitializeEntryElement(index, target); | 133 InitializeEntryElement(index, target); |
164 } | 134 } |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 entry_frame_->stack_pointer_ = stack_pointer; | 229 entry_frame_->stack_pointer_ = stack_pointer; |
260 } | 230 } |
261 | 231 |
262 | 232 |
263 void JumpTarget::Jump() { | 233 void JumpTarget::Jump() { |
264 DoJump(); | 234 DoJump(); |
265 } | 235 } |
266 | 236 |
267 | 237 |
268 void JumpTarget::Jump(Result* arg) { | 238 void JumpTarget::Jump(Result* arg) { |
269 ASSERT(cgen_ != NULL); | 239 ASSERT(cgen()->has_valid_frame()); |
270 ASSERT(cgen_->has_valid_frame()); | |
271 | 240 |
272 cgen_->frame()->Push(arg); | 241 cgen()->frame()->Push(arg); |
273 DoJump(); | 242 DoJump(); |
274 } | 243 } |
275 | 244 |
276 | 245 |
277 void JumpTarget::Jump(Result* arg0, Result* arg1) { | 246 void JumpTarget::Jump(Result* arg0, Result* arg1) { |
278 ASSERT(cgen_ != NULL); | 247 ASSERT(cgen()->has_valid_frame()); |
279 ASSERT(cgen_->has_valid_frame()); | |
280 | 248 |
281 cgen_->frame()->Push(arg0); | 249 cgen()->frame()->Push(arg0); |
282 cgen_->frame()->Push(arg1); | 250 cgen()->frame()->Push(arg1); |
283 DoJump(); | 251 DoJump(); |
284 } | 252 } |
285 | 253 |
286 | 254 |
287 void JumpTarget::Jump(Result* arg0, Result* arg1, Result* arg2) { | 255 void JumpTarget::Jump(Result* arg0, Result* arg1, Result* arg2) { |
288 ASSERT(cgen_ != NULL); | 256 ASSERT(cgen()->has_valid_frame()); |
289 ASSERT(cgen_->has_valid_frame()); | |
290 | 257 |
291 cgen_->frame()->Push(arg0); | 258 cgen()->frame()->Push(arg0); |
292 cgen_->frame()->Push(arg1); | 259 cgen()->frame()->Push(arg1); |
293 cgen_->frame()->Push(arg2); | 260 cgen()->frame()->Push(arg2); |
294 DoJump(); | 261 DoJump(); |
295 } | 262 } |
296 | 263 |
297 | 264 |
298 void JumpTarget::Branch(Condition cc, Hint hint) { | 265 void JumpTarget::Branch(Condition cc, Hint hint) { |
299 DoBranch(cc, hint); | 266 DoBranch(cc, hint); |
300 } | 267 } |
301 | 268 |
302 | 269 |
303 #ifdef DEBUG | 270 #ifdef DEBUG |
304 #define DECLARE_ARGCHECK_VARS(name) \ | 271 #define DECLARE_ARGCHECK_VARS(name) \ |
305 Result::Type name##_type = name->type(); \ | 272 Result::Type name##_type = name->type(); \ |
306 Register name##_reg = name->is_register() ? name->reg() : no_reg | 273 Register name##_reg = name->is_register() ? name->reg() : no_reg |
307 | 274 |
308 #define ASSERT_ARGCHECK(name) \ | 275 #define ASSERT_ARGCHECK(name) \ |
309 ASSERT(name->type() == name##_type); \ | 276 ASSERT(name->type() == name##_type); \ |
310 ASSERT(!name->is_register() || name->reg().is(name##_reg)) | 277 ASSERT(!name->is_register() || name->reg().is(name##_reg)) |
311 | 278 |
312 #else | 279 #else |
313 #define DECLARE_ARGCHECK_VARS(name) do {} while (false) | 280 #define DECLARE_ARGCHECK_VARS(name) do {} while (false) |
314 | 281 |
315 #define ASSERT_ARGCHECK(name) do {} while (false) | 282 #define ASSERT_ARGCHECK(name) do {} while (false) |
316 #endif | 283 #endif |
317 | 284 |
318 void JumpTarget::Branch(Condition cc, Result* arg, Hint hint) { | 285 void JumpTarget::Branch(Condition cc, Result* arg, Hint hint) { |
319 ASSERT(cgen_ != NULL); | 286 ASSERT(cgen()->has_valid_frame()); |
320 ASSERT(cgen_->has_valid_frame()); | |
321 | 287 |
322 // We want to check that non-frame registers at the call site stay in | 288 // We want to check that non-frame registers at the call site stay in |
323 // the same registers on the fall-through branch. | 289 // the same registers on the fall-through branch. |
324 DECLARE_ARGCHECK_VARS(arg); | 290 DECLARE_ARGCHECK_VARS(arg); |
325 | 291 |
326 cgen_->frame()->Push(arg); | 292 cgen()->frame()->Push(arg); |
327 DoBranch(cc, hint); | 293 DoBranch(cc, hint); |
328 *arg = cgen_->frame()->Pop(); | 294 *arg = cgen()->frame()->Pop(); |
329 | 295 |
330 ASSERT_ARGCHECK(arg); | 296 ASSERT_ARGCHECK(arg); |
331 } | 297 } |
332 | 298 |
333 | 299 |
334 void JumpTarget::Branch(Condition cc, Result* arg0, Result* arg1, Hint hint) { | 300 void JumpTarget::Branch(Condition cc, Result* arg0, Result* arg1, Hint hint) { |
335 ASSERT(cgen_ != NULL); | 301 ASSERT(cgen()->frame() != NULL); |
336 ASSERT(cgen_->frame() != NULL); | |
337 | 302 |
338 // We want to check that non-frame registers at the call site stay in | 303 // We want to check that non-frame registers at the call site stay in |
339 // the same registers on the fall-through branch. | 304 // the same registers on the fall-through branch. |
340 DECLARE_ARGCHECK_VARS(arg0); | 305 DECLARE_ARGCHECK_VARS(arg0); |
341 DECLARE_ARGCHECK_VARS(arg1); | 306 DECLARE_ARGCHECK_VARS(arg1); |
342 | 307 |
343 cgen_->frame()->Push(arg0); | 308 cgen()->frame()->Push(arg0); |
344 cgen_->frame()->Push(arg1); | 309 cgen()->frame()->Push(arg1); |
345 DoBranch(cc, hint); | 310 DoBranch(cc, hint); |
346 *arg1 = cgen_->frame()->Pop(); | 311 *arg1 = cgen()->frame()->Pop(); |
347 *arg0 = cgen_->frame()->Pop(); | 312 *arg0 = cgen()->frame()->Pop(); |
348 | 313 |
349 ASSERT_ARGCHECK(arg0); | 314 ASSERT_ARGCHECK(arg0); |
350 ASSERT_ARGCHECK(arg1); | 315 ASSERT_ARGCHECK(arg1); |
351 } | 316 } |
352 | 317 |
353 | 318 |
354 void JumpTarget::Branch(Condition cc, | 319 void JumpTarget::Branch(Condition cc, |
355 Result* arg0, | 320 Result* arg0, |
356 Result* arg1, | 321 Result* arg1, |
357 Result* arg2, | 322 Result* arg2, |
358 Hint hint) { | 323 Hint hint) { |
359 ASSERT(cgen_ != NULL); | 324 ASSERT(cgen()->frame() != NULL); |
360 ASSERT(cgen_->frame() != NULL); | |
361 | 325 |
362 // We want to check that non-frame registers at the call site stay in | 326 // We want to check that non-frame registers at the call site stay in |
363 // the same registers on the fall-through branch. | 327 // the same registers on the fall-through branch. |
364 DECLARE_ARGCHECK_VARS(arg0); | 328 DECLARE_ARGCHECK_VARS(arg0); |
365 DECLARE_ARGCHECK_VARS(arg1); | 329 DECLARE_ARGCHECK_VARS(arg1); |
366 DECLARE_ARGCHECK_VARS(arg2); | 330 DECLARE_ARGCHECK_VARS(arg2); |
367 | 331 |
368 cgen_->frame()->Push(arg0); | 332 cgen()->frame()->Push(arg0); |
369 cgen_->frame()->Push(arg1); | 333 cgen()->frame()->Push(arg1); |
370 cgen_->frame()->Push(arg2); | 334 cgen()->frame()->Push(arg2); |
371 DoBranch(cc, hint); | 335 DoBranch(cc, hint); |
372 *arg2 = cgen_->frame()->Pop(); | 336 *arg2 = cgen()->frame()->Pop(); |
373 *arg1 = cgen_->frame()->Pop(); | 337 *arg1 = cgen()->frame()->Pop(); |
374 *arg0 = cgen_->frame()->Pop(); | 338 *arg0 = cgen()->frame()->Pop(); |
375 | 339 |
376 ASSERT_ARGCHECK(arg0); | 340 ASSERT_ARGCHECK(arg0); |
377 ASSERT_ARGCHECK(arg1); | 341 ASSERT_ARGCHECK(arg1); |
378 ASSERT_ARGCHECK(arg2); | 342 ASSERT_ARGCHECK(arg2); |
379 } | 343 } |
380 | 344 |
381 | 345 |
382 void JumpTarget::Branch(Condition cc, | 346 void JumpTarget::Branch(Condition cc, |
383 Result* arg0, | 347 Result* arg0, |
384 Result* arg1, | 348 Result* arg1, |
385 Result* arg2, | 349 Result* arg2, |
386 Result* arg3, | 350 Result* arg3, |
387 Hint hint) { | 351 Hint hint) { |
388 ASSERT(cgen_ != NULL); | 352 ASSERT(cgen()->frame() != NULL); |
389 ASSERT(cgen_->frame() != NULL); | |
390 | 353 |
391 // We want to check that non-frame registers at the call site stay in | 354 // We want to check that non-frame registers at the call site stay in |
392 // the same registers on the fall-through branch. | 355 // the same registers on the fall-through branch. |
393 DECLARE_ARGCHECK_VARS(arg0); | 356 DECLARE_ARGCHECK_VARS(arg0); |
394 DECLARE_ARGCHECK_VARS(arg1); | 357 DECLARE_ARGCHECK_VARS(arg1); |
395 DECLARE_ARGCHECK_VARS(arg2); | 358 DECLARE_ARGCHECK_VARS(arg2); |
396 DECLARE_ARGCHECK_VARS(arg3); | 359 DECLARE_ARGCHECK_VARS(arg3); |
397 | 360 |
398 cgen_->frame()->Push(arg0); | 361 cgen()->frame()->Push(arg0); |
399 cgen_->frame()->Push(arg1); | 362 cgen()->frame()->Push(arg1); |
400 cgen_->frame()->Push(arg2); | 363 cgen()->frame()->Push(arg2); |
401 cgen_->frame()->Push(arg3); | 364 cgen()->frame()->Push(arg3); |
402 DoBranch(cc, hint); | 365 DoBranch(cc, hint); |
403 *arg3 = cgen_->frame()->Pop(); | 366 *arg3 = cgen()->frame()->Pop(); |
404 *arg2 = cgen_->frame()->Pop(); | 367 *arg2 = cgen()->frame()->Pop(); |
405 *arg1 = cgen_->frame()->Pop(); | 368 *arg1 = cgen()->frame()->Pop(); |
406 *arg0 = cgen_->frame()->Pop(); | 369 *arg0 = cgen()->frame()->Pop(); |
407 | 370 |
408 ASSERT_ARGCHECK(arg0); | 371 ASSERT_ARGCHECK(arg0); |
409 ASSERT_ARGCHECK(arg1); | 372 ASSERT_ARGCHECK(arg1); |
410 ASSERT_ARGCHECK(arg2); | 373 ASSERT_ARGCHECK(arg2); |
411 ASSERT_ARGCHECK(arg3); | 374 ASSERT_ARGCHECK(arg3); |
412 } | 375 } |
413 | 376 |
414 | 377 |
415 void BreakTarget::Branch(Condition cc, Result* arg, Hint hint) { | 378 void BreakTarget::Branch(Condition cc, Result* arg, Hint hint) { |
416 ASSERT(cgen_ != NULL); | 379 ASSERT(cgen()->has_valid_frame()); |
417 ASSERT(cgen_->has_valid_frame()); | |
418 | 380 |
419 int count = cgen_->frame()->height() - expected_height_; | 381 int count = cgen()->frame()->height() - expected_height_; |
420 if (count > 0) { | 382 if (count > 0) { |
421 // We negate and branch here rather than using DoBranch's negate | 383 // We negate and branch here rather than using DoBranch's negate |
422 // and branch. This gives us a hook to remove statement state | 384 // and branch. This gives us a hook to remove statement state |
423 // from the frame. | 385 // from the frame. |
424 JumpTarget fall_through(cgen_); | 386 JumpTarget fall_through; |
425 // Branch to fall through will not negate, because it is a | 387 // Branch to fall through will not negate, because it is a |
426 // forward-only target. | 388 // forward-only target. |
427 fall_through.Branch(NegateCondition(cc), NegateHint(hint)); | 389 fall_through.Branch(NegateCondition(cc), NegateHint(hint)); |
428 Jump(arg); // May emit merge code here. | 390 Jump(arg); // May emit merge code here. |
429 fall_through.Bind(); | 391 fall_through.Bind(); |
430 } else { | 392 } else { |
431 DECLARE_ARGCHECK_VARS(arg); | 393 DECLARE_ARGCHECK_VARS(arg); |
432 cgen_->frame()->Push(arg); | 394 cgen()->frame()->Push(arg); |
433 DoBranch(cc, hint); | 395 DoBranch(cc, hint); |
434 *arg = cgen_->frame()->Pop(); | 396 *arg = cgen()->frame()->Pop(); |
435 ASSERT_ARGCHECK(arg); | 397 ASSERT_ARGCHECK(arg); |
436 } | 398 } |
437 } | 399 } |
438 | 400 |
439 #undef DECLARE_ARGCHECK_VARS | 401 #undef DECLARE_ARGCHECK_VARS |
440 #undef ASSERT_ARGCHECK | 402 #undef ASSERT_ARGCHECK |
441 | 403 |
442 | 404 |
443 void JumpTarget::Bind(int mergable_elements) { | 405 void JumpTarget::Bind(int mergable_elements) { |
444 DoBind(mergable_elements); | 406 DoBind(mergable_elements); |
445 } | 407 } |
446 | 408 |
447 | 409 |
448 void JumpTarget::Bind(Result* arg, int mergable_elements) { | 410 void JumpTarget::Bind(Result* arg, int mergable_elements) { |
449 ASSERT(cgen_ != NULL); | 411 if (cgen()->has_valid_frame()) { |
450 | 412 cgen()->frame()->Push(arg); |
451 if (cgen_->has_valid_frame()) { | |
452 cgen_->frame()->Push(arg); | |
453 } | 413 } |
454 DoBind(mergable_elements); | 414 DoBind(mergable_elements); |
455 *arg = cgen_->frame()->Pop(); | 415 *arg = cgen()->frame()->Pop(); |
456 } | 416 } |
457 | 417 |
458 | 418 |
459 void JumpTarget::Bind(Result* arg0, Result* arg1, int mergable_elements) { | 419 void JumpTarget::Bind(Result* arg0, Result* arg1, int mergable_elements) { |
460 ASSERT(cgen_ != NULL); | 420 if (cgen()->has_valid_frame()) { |
461 | 421 cgen()->frame()->Push(arg0); |
462 if (cgen_->has_valid_frame()) { | 422 cgen()->frame()->Push(arg1); |
463 cgen_->frame()->Push(arg0); | |
464 cgen_->frame()->Push(arg1); | |
465 } | 423 } |
466 DoBind(mergable_elements); | 424 DoBind(mergable_elements); |
467 *arg1 = cgen_->frame()->Pop(); | 425 *arg1 = cgen()->frame()->Pop(); |
468 *arg0 = cgen_->frame()->Pop(); | 426 *arg0 = cgen()->frame()->Pop(); |
469 } | 427 } |
470 | 428 |
471 | 429 |
472 void JumpTarget::Bind(Result* arg0, | 430 void JumpTarget::Bind(Result* arg0, |
473 Result* arg1, | 431 Result* arg1, |
474 Result* arg2, | 432 Result* arg2, |
475 int mergable_elements) { | 433 int mergable_elements) { |
476 ASSERT(cgen_ != NULL); | 434 if (cgen()->has_valid_frame()) { |
477 | 435 cgen()->frame()->Push(arg0); |
478 if (cgen_->has_valid_frame()) { | 436 cgen()->frame()->Push(arg1); |
479 cgen_->frame()->Push(arg0); | 437 cgen()->frame()->Push(arg2); |
480 cgen_->frame()->Push(arg1); | |
481 cgen_->frame()->Push(arg2); | |
482 } | 438 } |
483 DoBind(mergable_elements); | 439 DoBind(mergable_elements); |
484 *arg2 = cgen_->frame()->Pop(); | 440 *arg2 = cgen()->frame()->Pop(); |
485 *arg1 = cgen_->frame()->Pop(); | 441 *arg1 = cgen()->frame()->Pop(); |
486 *arg0 = cgen_->frame()->Pop(); | 442 *arg0 = cgen()->frame()->Pop(); |
487 } | 443 } |
488 | 444 |
489 | 445 |
490 void JumpTarget::Bind(Result* arg0, | 446 void JumpTarget::Bind(Result* arg0, |
491 Result* arg1, | 447 Result* arg1, |
492 Result* arg2, | 448 Result* arg2, |
493 Result* arg3, | 449 Result* arg3, |
494 int mergable_elements) { | 450 int mergable_elements) { |
495 ASSERT(cgen_ != NULL); | 451 if (cgen()->has_valid_frame()) { |
496 | 452 cgen()->frame()->Push(arg0); |
497 if (cgen_->has_valid_frame()) { | 453 cgen()->frame()->Push(arg1); |
498 cgen_->frame()->Push(arg0); | 454 cgen()->frame()->Push(arg2); |
499 cgen_->frame()->Push(arg1); | 455 cgen()->frame()->Push(arg3); |
500 cgen_->frame()->Push(arg2); | |
501 cgen_->frame()->Push(arg3); | |
502 } | 456 } |
503 DoBind(mergable_elements); | 457 DoBind(mergable_elements); |
504 *arg3 = cgen_->frame()->Pop(); | 458 *arg3 = cgen()->frame()->Pop(); |
505 *arg2 = cgen_->frame()->Pop(); | 459 *arg2 = cgen()->frame()->Pop(); |
506 *arg1 = cgen_->frame()->Pop(); | 460 *arg1 = cgen()->frame()->Pop(); |
507 *arg0 = cgen_->frame()->Pop(); | 461 *arg0 = cgen()->frame()->Pop(); |
508 } | 462 } |
509 | 463 |
510 | 464 |
511 void JumpTarget::AddReachingFrame(VirtualFrame* frame) { | 465 void JumpTarget::AddReachingFrame(VirtualFrame* frame) { |
512 ASSERT(reaching_frames_.length() == merge_labels_.length()); | 466 ASSERT(reaching_frames_.length() == merge_labels_.length()); |
513 ASSERT(entry_frame_ == NULL); | 467 ASSERT(entry_frame_ == NULL); |
514 Label fresh; | 468 Label fresh; |
515 merge_labels_.Add(fresh); | 469 merge_labels_.Add(fresh); |
516 reaching_frames_.Add(frame); | 470 reaching_frames_.Add(frame); |
517 } | 471 } |
518 | 472 |
519 | 473 |
520 // ------------------------------------------------------------------------- | 474 // ------------------------------------------------------------------------- |
521 // BreakTarget implementation. | 475 // BreakTarget implementation. |
522 | 476 |
523 void BreakTarget::Initialize(CodeGenerator* cgen, Directionality direction) { | 477 void BreakTarget::set_direction(Directionality direction) { |
524 JumpTarget::Initialize(cgen, direction); | 478 JumpTarget::set_direction(direction); |
525 ASSERT(cgen_->has_valid_frame()); | 479 ASSERT(cgen()->has_valid_frame()); |
526 expected_height_ = cgen_->frame()->height(); | 480 expected_height_ = cgen()->frame()->height(); |
527 } | 481 } |
528 | 482 |
529 | 483 |
530 void BreakTarget::CopyTo(BreakTarget* destination) { | 484 void BreakTarget::CopyTo(BreakTarget* destination) { |
531 ASSERT(destination != NULL); | 485 ASSERT(destination != NULL); |
532 destination->cgen_ = cgen_; | |
533 destination->masm_ = masm_; | |
534 destination->direction_ = direction_; | 486 destination->direction_ = direction_; |
535 destination->reaching_frames_.Clear(); | 487 destination->reaching_frames_.Clear(); |
536 destination->merge_labels_.Clear(); | 488 destination->merge_labels_.Clear(); |
537 ASSERT(reaching_frames_.length() == merge_labels_.length()); | 489 ASSERT(reaching_frames_.length() == merge_labels_.length()); |
538 for (int i = 0; i < reaching_frames_.length(); i++) { | 490 for (int i = 0; i < reaching_frames_.length(); i++) { |
539 destination->reaching_frames_.Add(reaching_frames_[i]); | 491 destination->reaching_frames_.Add(reaching_frames_[i]); |
540 destination->merge_labels_.Add(merge_labels_[i]); | 492 destination->merge_labels_.Add(merge_labels_[i]); |
541 } | 493 } |
542 destination->entry_frame_ = entry_frame_; | 494 destination->entry_frame_ = entry_frame_; |
543 destination->entry_label_ = entry_label_; | 495 destination->entry_label_ = entry_label_; |
544 destination->expected_height_ = expected_height_; | 496 destination->expected_height_ = expected_height_; |
545 } | 497 } |
546 | 498 |
547 | 499 |
548 void BreakTarget::Jump() { | 500 void BreakTarget::Jump() { |
549 ASSERT(cgen_ != NULL); | 501 ASSERT(cgen()->has_valid_frame()); |
550 ASSERT(cgen_->has_valid_frame()); | |
551 | 502 |
552 // Drop leftover statement state from the frame before merging. | 503 // Drop leftover statement state from the frame before merging. |
553 cgen_->frame()->ForgetElements(cgen_->frame()->height() - expected_height_); | 504 cgen()->frame()->ForgetElements(cgen()->frame()->height() - expected_height_); |
554 DoJump(); | 505 DoJump(); |
555 } | 506 } |
556 | 507 |
557 | 508 |
558 void BreakTarget::Jump(Result* arg) { | 509 void BreakTarget::Jump(Result* arg) { |
559 ASSERT(cgen_ != NULL); | 510 ASSERT(cgen()->has_valid_frame()); |
560 ASSERT(cgen_->has_valid_frame()); | |
561 | 511 |
562 // Drop leftover statement state from the frame before merging. | 512 // Drop leftover statement state from the frame before merging. |
563 cgen_->frame()->ForgetElements(cgen_->frame()->height() - expected_height_); | 513 cgen()->frame()->ForgetElements(cgen()->frame()->height() - expected_height_); |
564 cgen_->frame()->Push(arg); | 514 cgen()->frame()->Push(arg); |
565 DoJump(); | 515 DoJump(); |
566 } | 516 } |
567 | 517 |
568 | 518 |
569 void BreakTarget::Branch(Condition cc, Hint hint) { | 519 void BreakTarget::Branch(Condition cc, Hint hint) { |
570 ASSERT(cgen_ != NULL); | 520 ASSERT(cgen()->has_valid_frame()); |
571 ASSERT(cgen_->has_valid_frame()); | |
572 | 521 |
573 int count = cgen_->frame()->height() - expected_height_; | 522 int count = cgen()->frame()->height() - expected_height_; |
574 if (count > 0) { | 523 if (count > 0) { |
575 // We negate and branch here rather than using DoBranch's negate | 524 // We negate and branch here rather than using DoBranch's negate |
576 // and branch. This gives us a hook to remove statement state | 525 // and branch. This gives us a hook to remove statement state |
577 // from the frame. | 526 // from the frame. |
578 JumpTarget fall_through(cgen_); | 527 JumpTarget fall_through; |
579 // Branch to fall through will not negate, because it is a | 528 // Branch to fall through will not negate, because it is a |
580 // forward-only target. | 529 // forward-only target. |
581 fall_through.Branch(NegateCondition(cc), NegateHint(hint)); | 530 fall_through.Branch(NegateCondition(cc), NegateHint(hint)); |
582 Jump(); // May emit merge code here. | 531 Jump(); // May emit merge code here. |
583 fall_through.Bind(); | 532 fall_through.Bind(); |
584 } else { | 533 } else { |
585 DoBranch(cc, hint); | 534 DoBranch(cc, hint); |
586 } | 535 } |
587 } | 536 } |
588 | 537 |
589 | 538 |
590 void BreakTarget::Bind(int mergable_elements) { | 539 void BreakTarget::Bind(int mergable_elements) { |
591 #ifdef DEBUG | 540 #ifdef DEBUG |
592 ASSERT(cgen_ != NULL); | |
593 // All the forward-reaching frames should have been adjusted at the | 541 // All the forward-reaching frames should have been adjusted at the |
594 // jumps to this target. | 542 // jumps to this target. |
595 for (int i = 0; i < reaching_frames_.length(); i++) { | 543 for (int i = 0; i < reaching_frames_.length(); i++) { |
596 ASSERT(reaching_frames_[i] == NULL || | 544 ASSERT(reaching_frames_[i] == NULL || |
597 reaching_frames_[i]->height() == expected_height_); | 545 reaching_frames_[i]->height() == expected_height_); |
598 } | 546 } |
599 #endif | 547 #endif |
600 // Drop leftover statement state from the frame before merging, even | 548 // Drop leftover statement state from the frame before merging, even |
601 // on the fall through. This is so we can bind the return target | 549 // on the fall through. This is so we can bind the return target |
602 // with state on the frame. | 550 // with state on the frame. |
603 if (cgen_->has_valid_frame()) { | 551 if (cgen()->has_valid_frame()) { |
604 cgen_->frame()->ForgetElements(cgen_->frame()->height() - expected_height_); | 552 int count = cgen()->frame()->height() - expected_height_; |
| 553 cgen()->frame()->ForgetElements(count); |
605 } | 554 } |
606 DoBind(mergable_elements); | 555 DoBind(mergable_elements); |
607 } | 556 } |
608 | 557 |
609 | 558 |
610 void BreakTarget::Bind(Result* arg, int mergable_elements) { | 559 void BreakTarget::Bind(Result* arg, int mergable_elements) { |
611 #ifdef DEBUG | 560 #ifdef DEBUG |
612 ASSERT(cgen_ != NULL); | |
613 // All the forward-reaching frames should have been adjusted at the | 561 // All the forward-reaching frames should have been adjusted at the |
614 // jumps to this target. | 562 // jumps to this target. |
615 for (int i = 0; i < reaching_frames_.length(); i++) { | 563 for (int i = 0; i < reaching_frames_.length(); i++) { |
616 ASSERT(reaching_frames_[i] == NULL || | 564 ASSERT(reaching_frames_[i] == NULL || |
617 reaching_frames_[i]->height() == expected_height_ + 1); | 565 reaching_frames_[i]->height() == expected_height_ + 1); |
618 } | 566 } |
619 #endif | 567 #endif |
620 // Drop leftover statement state from the frame before merging, even | 568 // Drop leftover statement state from the frame before merging, even |
621 // on the fall through. This is so we can bind the return target | 569 // on the fall through. This is so we can bind the return target |
622 // with state on the frame. | 570 // with state on the frame. |
623 if (cgen_->has_valid_frame()) { | 571 if (cgen()->has_valid_frame()) { |
624 cgen_->frame()->ForgetElements(cgen_->frame()->height() - expected_height_); | 572 int count = cgen()->frame()->height() - expected_height_; |
625 cgen_->frame()->Push(arg); | 573 cgen()->frame()->ForgetElements(count); |
| 574 cgen()->frame()->Push(arg); |
626 } | 575 } |
627 DoBind(mergable_elements); | 576 DoBind(mergable_elements); |
628 *arg = cgen_->frame()->Pop(); | 577 *arg = cgen()->frame()->Pop(); |
629 } | 578 } |
630 | 579 |
631 | 580 |
632 // ------------------------------------------------------------------------- | 581 // ------------------------------------------------------------------------- |
633 // ShadowTarget implementation. | 582 // ShadowTarget implementation. |
634 | 583 |
635 ShadowTarget::ShadowTarget(BreakTarget* shadowed) { | 584 ShadowTarget::ShadowTarget(BreakTarget* shadowed) { |
636 ASSERT(shadowed != NULL); | 585 ASSERT(shadowed != NULL); |
637 other_target_ = shadowed; | 586 other_target_ = shadowed; |
638 | 587 |
639 #ifdef DEBUG | 588 #ifdef DEBUG |
640 is_shadowing_ = true; | 589 is_shadowing_ = true; |
641 #endif | 590 #endif |
642 // While shadowing this shadow target saves the state of the original. | 591 // While shadowing this shadow target saves the state of the original. |
643 shadowed->CopyTo(this); | 592 shadowed->CopyTo(this); |
644 | 593 |
645 // The original's state is reset. | 594 // The original's state is reset. |
646 shadowed->Unuse(); | 595 shadowed->Unuse(); |
647 ASSERT(cgen_ != NULL); | 596 ASSERT(cgen()->has_valid_frame()); |
648 ASSERT(cgen_->has_valid_frame()); | 597 shadowed->set_expected_height(cgen()->frame()->height()); |
649 shadowed->set_expected_height(cgen_->frame()->height()); | |
650 | |
651 // Setting the code generator to null prevents the shadow target from | |
652 // being used until shadowing stops. | |
653 cgen_ = NULL; | |
654 masm_ = NULL; | |
655 } | 598 } |
656 | 599 |
657 | 600 |
658 void ShadowTarget::StopShadowing() { | 601 void ShadowTarget::StopShadowing() { |
659 ASSERT(is_shadowing_); | 602 ASSERT(is_shadowing_); |
660 | 603 |
661 // This target does not have a valid code generator yet. | |
662 cgen_ = other_target_->code_generator(); | |
663 ASSERT(cgen_ != NULL); | |
664 masm_ = cgen_->masm(); | |
665 | |
666 // The states of this target, which was shadowed, and the original | 604 // The states of this target, which was shadowed, and the original |
667 // target, which was shadowing, are swapped. | 605 // target, which was shadowing, are swapped. |
668 BreakTarget temp; | 606 BreakTarget temp; |
669 other_target_->CopyTo(&temp); | 607 other_target_->CopyTo(&temp); |
670 CopyTo(other_target_); | 608 CopyTo(other_target_); |
671 temp.CopyTo(this); | 609 temp.CopyTo(this); |
672 temp.Unuse(); | 610 temp.Unuse(); |
673 | 611 |
674 #ifdef DEBUG | 612 #ifdef DEBUG |
675 is_shadowing_ = false; | 613 is_shadowing_ = false; |
676 #endif | 614 #endif |
677 } | 615 } |
678 | 616 |
679 | 617 |
680 } } // namespace v8::internal | 618 } } // namespace v8::internal |
OLD | NEW |