| OLD | NEW |
| 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
| 2 // All Rights Reserved. | 2 // All Rights Reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions | 5 // modification, are permitted provided that the following conditions |
| 6 // are met: | 6 // are met: |
| 7 // | 7 // |
| 8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
| 9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
| 10 // | 10 // |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) { | 330 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) { |
| 331 spare_buffer_ = buffer_; | 331 spare_buffer_ = buffer_; |
| 332 } else { | 332 } else { |
| 333 DeleteArray(buffer_); | 333 DeleteArray(buffer_); |
| 334 } | 334 } |
| 335 } | 335 } |
| 336 } | 336 } |
| 337 | 337 |
| 338 | 338 |
| 339 void Assembler::GetCode(CodeDesc* desc) { | 339 void Assembler::GetCode(CodeDesc* desc) { |
| 340 // finalize code | |
| 341 if (unbound_label_.is_linked()) | |
| 342 bind_to(&unbound_label_, binding_pos_); | |
| 343 | |
| 344 // emit constant pool if necessary | 340 // emit constant pool if necessary |
| 345 CheckConstPool(true, false); | 341 CheckConstPool(true, false); |
| 346 ASSERT(num_prinfo_ == 0); | 342 ASSERT(num_prinfo_ == 0); |
| 347 | 343 |
| 348 // setup desc | 344 // setup desc |
| 349 desc->buffer = buffer_; | 345 desc->buffer = buffer_; |
| 350 desc->buffer_size = buffer_size_; | 346 desc->buffer_size = buffer_size_; |
| 351 desc->instr_size = pc_offset(); | 347 desc->instr_size = pc_offset(); |
| 352 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); | 348 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); |
| 353 } | 349 } |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 462 | 458 |
| 463 void Assembler::bind_to(Label* L, int pos) { | 459 void Assembler::bind_to(Label* L, int pos) { |
| 464 ASSERT(0 <= pos && pos <= pc_offset()); // must have a valid binding position | 460 ASSERT(0 <= pos && pos <= pc_offset()); // must have a valid binding position |
| 465 while (L->is_linked()) { | 461 while (L->is_linked()) { |
| 466 int fixup_pos = L->pos(); | 462 int fixup_pos = L->pos(); |
| 467 next(L); // call next before overwriting link with target at fixup_pos | 463 next(L); // call next before overwriting link with target at fixup_pos |
| 468 target_at_put(fixup_pos, pos); | 464 target_at_put(fixup_pos, pos); |
| 469 } | 465 } |
| 470 L->bind_to(pos); | 466 L->bind_to(pos); |
| 471 | 467 |
| 472 // do not eliminate jump instructions before the last bound position | 468 // Keep track of the last bound label so we don't eliminate any instructions |
| 473 if (pos > last_bound_pos_) | 469 // before a bound label. |
| 470 if (pos > last_bound_pos_) |
| 474 last_bound_pos_ = pos; | 471 last_bound_pos_ = pos; |
| 475 } | 472 } |
| 476 | 473 |
| 477 | 474 |
| 478 void Assembler::link_to(Label* L, Label* appendix) { | 475 void Assembler::link_to(Label* L, Label* appendix) { |
| 479 if (appendix->is_linked()) { | 476 if (appendix->is_linked()) { |
| 480 if (L->is_linked()) { | 477 if (L->is_linked()) { |
| 481 // append appendix to L's list | 478 // append appendix to L's list |
| 482 int fixup_pos; | 479 int fixup_pos; |
| 483 int link = L->pos(); | 480 int link = L->pos(); |
| 484 do { | 481 do { |
| 485 fixup_pos = link; | 482 fixup_pos = link; |
| 486 link = target_at(fixup_pos); | 483 link = target_at(fixup_pos); |
| 487 } while (link > 0); | 484 } while (link > 0); |
| 488 ASSERT(link == kEndOfChain); | 485 ASSERT(link == kEndOfChain); |
| 489 target_at_put(fixup_pos, appendix->pos()); | 486 target_at_put(fixup_pos, appendix->pos()); |
| 490 } else { | 487 } else { |
| 491 // L is empty, simply use appendix | 488 // L is empty, simply use appendix |
| 492 *L = *appendix; | 489 *L = *appendix; |
| 493 } | 490 } |
| 494 } | 491 } |
| 495 appendix->Unuse(); // appendix should not be used anymore | 492 appendix->Unuse(); // appendix should not be used anymore |
| 496 } | 493 } |
| 497 | 494 |
| 498 | 495 |
| 499 void Assembler::bind(Label* L) { | 496 void Assembler::bind(Label* L) { |
| 500 ASSERT(!L->is_bound()); // label can only be bound once | 497 ASSERT(!L->is_bound()); // label can only be bound once |
| 501 if (FLAG_eliminate_jumps) { | |
| 502 // Resolve unbound label. | |
| 503 if (unbound_label_.is_linked()) { | |
| 504 // Unbound label exists => link it with L if same binding | |
| 505 // position, otherwise fix it. | |
| 506 if (binding_pos_ == pc_offset()) { | |
| 507 // Link it to L's list. | |
| 508 link_to(L, &unbound_label_); | |
| 509 } else { | |
| 510 // Otherwise bind unbound label. | |
| 511 ASSERT(binding_pos_ < pc_offset()); | |
| 512 bind_to(&unbound_label_, binding_pos_); | |
| 513 } | |
| 514 } | |
| 515 ASSERT(!unbound_label_.is_linked()); | |
| 516 // Try to eliminate jumps to next instruction. | |
| 517 Instr instr; | |
| 518 // Do not remove an already bound jump target. | |
| 519 while (last_bound_pos_ < pc_offset() && | |
| 520 reloc_info_writer.last_pc() <= pc_ - kInstrSize && | |
| 521 L->is_linked() && L->pos() == pc_offset() - kInstrSize && | |
| 522 (((instr = instr_at(L->pos())) & CondMask) != nv && // not blx | |
| 523 (instr & 15*B24) == 10*B24)) { // b<cond>, but not bl<cond> | |
| 524 // Previous instruction is b<cond> jumping immediately after it | |
| 525 // => eliminate it | |
| 526 if (FLAG_print_jump_elimination) | |
| 527 PrintF("@ %d jump to next eliminated\n", L->pos()); | |
| 528 // Remove first entry from label list. | |
| 529 next(L); | |
| 530 // Eliminate instruction (set code pointers back). | |
| 531 pc_ -= kInstrSize; | |
| 532 // Make sure not to skip relocation information when rewinding. | |
| 533 ASSERT(reloc_info_writer.last_pc() <= pc_); | |
| 534 } | |
| 535 // delay fixup of L => store it as unbound label | |
| 536 unbound_label_ = *L; | |
| 537 binding_pos_ = pc_offset(); | |
| 538 L->Unuse(); | |
| 539 } | |
| 540 bind_to(L, pc_offset()); | 498 bind_to(L, pc_offset()); |
| 541 } | 499 } |
| 542 | 500 |
| 543 | 501 |
| 544 void Assembler::next(Label* L) { | 502 void Assembler::next(Label* L) { |
| 545 ASSERT(L->is_linked()); | 503 ASSERT(L->is_linked()); |
| 546 int link = target_at(L->pos()); | 504 int link = target_at(L->pos()); |
| 547 if (link > 0) { | 505 if (link > 0) { |
| 548 L->link_to(link); | 506 L->link_to(link); |
| 549 } else { | 507 } else { |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 721 // post-indexed addressing requires W == 1; different than in addrmod2/3 | 679 // post-indexed addressing requires W == 1; different than in addrmod2/3 |
| 722 if ((am & P) == 0) | 680 if ((am & P) == 0) |
| 723 am |= W; | 681 am |= W; |
| 724 | 682 |
| 725 ASSERT(offset_8 >= 0); // no masking needed | 683 ASSERT(offset_8 >= 0); // no masking needed |
| 726 emit(instr | am | x.rn_.code()*B16 | crd.code()*B12 | offset_8); | 684 emit(instr | am | x.rn_.code()*B16 | crd.code()*B12 | offset_8); |
| 727 } | 685 } |
| 728 | 686 |
| 729 | 687 |
| 730 int Assembler::branch_offset(Label* L, bool jump_elimination_allowed) { | 688 int Assembler::branch_offset(Label* L, bool jump_elimination_allowed) { |
| 731 // if we emit an unconditional jump/call and if the current position is the | |
| 732 // target of the unbound label, we can change the binding position of the | |
| 733 // unbound label, thereby eliminating an unnecessary jump | |
| 734 bool can_eliminate = false; | |
| 735 if (jump_elimination_allowed && FLAG_eliminate_jumps && | |
| 736 unbound_label_.is_linked() && binding_pos_ == pc_offset()) { | |
| 737 can_eliminate = true; | |
| 738 if (FLAG_print_jump_elimination) { | |
| 739 PrintF("eliminated jumps/calls to %d from ", binding_pos_); | |
| 740 print(&unbound_label_); | |
| 741 } | |
| 742 } | |
| 743 int target_pos; | 689 int target_pos; |
| 744 if (L->is_bound()) { | 690 if (L->is_bound()) { |
| 745 target_pos = L->pos(); | 691 target_pos = L->pos(); |
| 746 if (can_eliminate) | |
| 747 binding_pos_ = target_pos; | |
| 748 } else { | 692 } else { |
| 749 if (can_eliminate) | 693 if (L->is_linked()) { |
| 750 link_to(L, &unbound_label_); // may modify L's link | |
| 751 if (L->is_linked()) | |
| 752 target_pos = L->pos(); // L's link | 694 target_pos = L->pos(); // L's link |
| 753 else | 695 } else { |
| 754 target_pos = kEndOfChain; | 696 target_pos = kEndOfChain; |
| 697 } |
| 755 L->link_to(pc_offset()); | 698 L->link_to(pc_offset()); |
| 756 } | 699 } |
| 757 | 700 |
| 758 // Block the emission of the constant pool, since the branch instruction must | 701 // Block the emission of the constant pool, since the branch instruction must |
| 759 // be emitted at the pc offset recorded by the label | 702 // be emitted at the pc offset recorded by the label |
| 760 BlockConstPoolBefore(pc_offset() + kInstrSize); | 703 BlockConstPoolBefore(pc_offset() + kInstrSize); |
| 761 | 704 |
| 762 return target_pos - pc_offset() - 8; | 705 return target_pos - pc_offset() - 8; |
| 763 } | 706 } |
| 764 | 707 |
| (...skipping 785 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1550 bind(&after_pool); | 1493 bind(&after_pool); |
| 1551 } | 1494 } |
| 1552 | 1495 |
| 1553 // Since a constant pool was just emitted, move the check offset forward by | 1496 // Since a constant pool was just emitted, move the check offset forward by |
| 1554 // the standard interval. | 1497 // the standard interval. |
| 1555 next_buffer_check_ = pc_offset() + kCheckConstInterval; | 1498 next_buffer_check_ = pc_offset() + kCheckConstInterval; |
| 1556 } | 1499 } |
| 1557 | 1500 |
| 1558 | 1501 |
| 1559 } } // namespace v8::internal | 1502 } } // namespace v8::internal |
| OLD | NEW |