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 18 matching lines...) Expand all Loading... |
29 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 29 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
31 // OF THE POSSIBILITY OF SUCH DAMAGE. | 31 // OF THE POSSIBILITY OF SUCH DAMAGE. |
32 | 32 |
33 // The original source code covered by the above license above has been modified | 33 // The original source code covered by the above license above has been modified |
34 // significantly by Google Inc. | 34 // significantly by Google Inc. |
35 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 35 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
36 | 36 |
37 #include "v8.h" | 37 #include "v8.h" |
38 | 38 |
| 39 #if defined(V8_TARGET_ARCH_IA32) |
| 40 |
39 #include "disassembler.h" | 41 #include "disassembler.h" |
40 #include "macro-assembler.h" | 42 #include "macro-assembler.h" |
41 #include "serialize.h" | 43 #include "serialize.h" |
42 | 44 |
43 namespace v8 { | 45 namespace v8 { |
44 namespace internal { | 46 namespace internal { |
45 | 47 |
46 // ----------------------------------------------------------------------------- | 48 // ----------------------------------------------------------------------------- |
47 // Implementation of CpuFeatures | 49 // Implementation of CpuFeatures |
48 | 50 |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 | 155 |
154 // ----------------------------------------------------------------------------- | 156 // ----------------------------------------------------------------------------- |
155 // Implementation of RelocInfo | 157 // Implementation of RelocInfo |
156 | 158 |
157 | 159 |
158 const int RelocInfo::kApplyMask = | 160 const int RelocInfo::kApplyMask = |
159 RelocInfo::kCodeTargetMask | 1 << RelocInfo::RUNTIME_ENTRY | | 161 RelocInfo::kCodeTargetMask | 1 << RelocInfo::RUNTIME_ENTRY | |
160 1 << RelocInfo::JS_RETURN | 1 << RelocInfo::INTERNAL_REFERENCE; | 162 1 << RelocInfo::JS_RETURN | 1 << RelocInfo::INTERNAL_REFERENCE; |
161 | 163 |
162 | 164 |
| 165 bool RelocInfo::IsCodedSpecially() { |
| 166 // The deserializer needs to know whether a pointer is specially coded. Being |
| 167 // specially coded on IA32 means that it is a relative address, as used by |
| 168 // branch instructions. These are also the ones that need changing when a |
| 169 // code object moves. |
| 170 return (1 << rmode_) & kApplyMask; |
| 171 } |
| 172 |
| 173 |
163 void RelocInfo::PatchCode(byte* instructions, int instruction_count) { | 174 void RelocInfo::PatchCode(byte* instructions, int instruction_count) { |
164 // Patch the code at the current address with the supplied instructions. | 175 // Patch the code at the current address with the supplied instructions. |
165 for (int i = 0; i < instruction_count; i++) { | 176 for (int i = 0; i < instruction_count; i++) { |
166 *(pc_ + i) = *(instructions + i); | 177 *(pc_ + i) = *(instructions + i); |
167 } | 178 } |
168 | 179 |
169 // Indicate that code has changed. | 180 // Indicate that code has changed. |
170 CPU::FlushICache(pc_, instruction_count); | 181 CPU::FlushICache(pc_, instruction_count); |
171 } | 182 } |
172 | 183 |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 void Assembler::push(const Operand& src) { | 437 void Assembler::push(const Operand& src) { |
427 EnsureSpace ensure_space(this); | 438 EnsureSpace ensure_space(this); |
428 last_pc_ = pc_; | 439 last_pc_ = pc_; |
429 EMIT(0xFF); | 440 EMIT(0xFF); |
430 emit_operand(esi, src); | 441 emit_operand(esi, src); |
431 } | 442 } |
432 | 443 |
433 | 444 |
434 void Assembler::pop(Register dst) { | 445 void Assembler::pop(Register dst) { |
435 ASSERT(reloc_info_writer.last_pc() != NULL); | 446 ASSERT(reloc_info_writer.last_pc() != NULL); |
436 if (FLAG_push_pop_elimination && (reloc_info_writer.last_pc() <= last_pc_)) { | 447 if (FLAG_peephole_optimization && (reloc_info_writer.last_pc() <= last_pc_)) { |
437 // (last_pc_ != NULL) is rolled into the above check. | 448 // (last_pc_ != NULL) is rolled into the above check. |
438 // If a last_pc_ is set, we need to make sure that there has not been any | 449 // If a last_pc_ is set, we need to make sure that there has not been any |
439 // relocation information generated between the last instruction and this | 450 // relocation information generated between the last instruction and this |
440 // pop instruction. | 451 // pop instruction. |
441 byte instr = last_pc_[0]; | 452 byte instr = last_pc_[0]; |
442 if ((instr & ~0x7) == 0x50) { | 453 if ((instr & ~0x7) == 0x50) { |
443 int push_reg_code = instr & 0x7; | 454 int push_reg_code = instr & 0x7; |
444 if (push_reg_code == dst.code()) { | 455 if (push_reg_code == dst.code()) { |
445 pc_ = last_pc_; | 456 pc_ = last_pc_; |
446 if (FLAG_print_push_pop_elimination) { | 457 if (FLAG_print_peephole_optimization) { |
447 PrintF("%d push/pop (same reg) eliminated\n", pc_offset()); | 458 PrintF("%d push/pop (same reg) eliminated\n", pc_offset()); |
448 } | 459 } |
449 } else { | 460 } else { |
450 // Convert 'push src; pop dst' to 'mov dst, src'. | 461 // Convert 'push src; pop dst' to 'mov dst, src'. |
451 last_pc_[0] = 0x8b; | 462 last_pc_[0] = 0x8b; |
452 Register src = { push_reg_code }; | 463 Register src = { push_reg_code }; |
453 EnsureSpace ensure_space(this); | 464 EnsureSpace ensure_space(this); |
454 emit_operand(dst, Operand(src)); | 465 emit_operand(dst, Operand(src)); |
455 if (FLAG_print_push_pop_elimination) { | 466 if (FLAG_print_peephole_optimization) { |
456 PrintF("%d push/pop (reg->reg) eliminated\n", pc_offset()); | 467 PrintF("%d push/pop (reg->reg) eliminated\n", pc_offset()); |
457 } | 468 } |
458 } | 469 } |
459 last_pc_ = NULL; | 470 last_pc_ = NULL; |
460 return; | 471 return; |
461 } else if (instr == 0xff) { // push of an operand, convert to a move | 472 } else if (instr == 0xff) { // push of an operand, convert to a move |
462 byte op1 = last_pc_[1]; | 473 byte op1 = last_pc_[1]; |
463 // Check if the operation is really a push. | 474 // Check if the operation is really a push. |
464 if ((op1 & 0x38) == (6 << 3)) { | 475 if ((op1 & 0x38) == (6 << 3)) { |
465 op1 = (op1 & ~0x38) | static_cast<byte>(dst.code() << 3); | 476 op1 = (op1 & ~0x38) | static_cast<byte>(dst.code() << 3); |
466 last_pc_[0] = 0x8b; | 477 last_pc_[0] = 0x8b; |
467 last_pc_[1] = op1; | 478 last_pc_[1] = op1; |
468 last_pc_ = NULL; | 479 last_pc_ = NULL; |
469 if (FLAG_print_push_pop_elimination) { | 480 if (FLAG_print_peephole_optimization) { |
470 PrintF("%d push/pop (op->reg) eliminated\n", pc_offset()); | 481 PrintF("%d push/pop (op->reg) eliminated\n", pc_offset()); |
471 } | 482 } |
472 return; | 483 return; |
473 } | 484 } |
474 } else if ((instr == 0x89) && | 485 } else if ((instr == 0x89) && |
475 (last_pc_[1] == 0x04) && | 486 (last_pc_[1] == 0x04) && |
476 (last_pc_[2] == 0x24)) { | 487 (last_pc_[2] == 0x24)) { |
477 // 0x71283c 396 890424 mov [esp],eax | 488 // 0x71283c 396 890424 mov [esp],eax |
478 // 0x71283f 399 58 pop eax | 489 // 0x71283f 399 58 pop eax |
479 if (dst.is(eax)) { | 490 if (dst.is(eax)) { |
480 // change to | 491 // change to |
481 // 0x710fac 216 83c404 add esp,0x4 | 492 // 0x710fac 216 83c404 add esp,0x4 |
482 last_pc_[0] = 0x83; | 493 last_pc_[0] = 0x83; |
483 last_pc_[1] = 0xc4; | 494 last_pc_[1] = 0xc4; |
484 last_pc_[2] = 0x04; | 495 last_pc_[2] = 0x04; |
485 last_pc_ = NULL; | 496 last_pc_ = NULL; |
486 if (FLAG_print_push_pop_elimination) { | 497 if (FLAG_print_peephole_optimization) { |
487 PrintF("%d push/pop (mov-pop) eliminated\n", pc_offset()); | 498 PrintF("%d push/pop (mov-pop) eliminated\n", pc_offset()); |
488 } | 499 } |
489 return; | 500 return; |
490 } | 501 } |
491 } else if (instr == 0x6a && dst.is(eax)) { // push of immediate 8 bit | 502 } else if (instr == 0x6a && dst.is(eax)) { // push of immediate 8 bit |
492 byte imm8 = last_pc_[1]; | 503 byte imm8 = last_pc_[1]; |
493 if (imm8 == 0) { | 504 if (imm8 == 0) { |
494 // 6a00 push 0x0 | 505 // 6a00 push 0x0 |
495 // 58 pop eax | 506 // 58 pop eax |
496 last_pc_[0] = 0x31; | 507 last_pc_[0] = 0x31; |
497 last_pc_[1] = 0xc0; | 508 last_pc_[1] = 0xc0; |
498 // change to | 509 // change to |
499 // 31c0 xor eax,eax | 510 // 31c0 xor eax,eax |
500 last_pc_ = NULL; | 511 last_pc_ = NULL; |
501 if (FLAG_print_push_pop_elimination) { | 512 if (FLAG_print_peephole_optimization) { |
502 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset()); | 513 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset()); |
503 } | 514 } |
504 return; | 515 return; |
505 } else { | 516 } else { |
506 // 6a00 push 0xXX | 517 // 6a00 push 0xXX |
507 // 58 pop eax | 518 // 58 pop eax |
508 last_pc_[0] = 0xb8; | 519 last_pc_[0] = 0xb8; |
509 EnsureSpace ensure_space(this); | 520 EnsureSpace ensure_space(this); |
510 if ((imm8 & 0x80) != 0) { | 521 if ((imm8 & 0x80) != 0) { |
511 EMIT(0xff); | 522 EMIT(0xff); |
512 EMIT(0xff); | 523 EMIT(0xff); |
513 EMIT(0xff); | 524 EMIT(0xff); |
514 // change to | 525 // change to |
515 // b8XXffffff mov eax,0xffffffXX | 526 // b8XXffffff mov eax,0xffffffXX |
516 } else { | 527 } else { |
517 EMIT(0x00); | 528 EMIT(0x00); |
518 EMIT(0x00); | 529 EMIT(0x00); |
519 EMIT(0x00); | 530 EMIT(0x00); |
520 // change to | 531 // change to |
521 // b8XX000000 mov eax,0x000000XX | 532 // b8XX000000 mov eax,0x000000XX |
522 } | 533 } |
523 last_pc_ = NULL; | 534 last_pc_ = NULL; |
524 if (FLAG_print_push_pop_elimination) { | 535 if (FLAG_print_peephole_optimization) { |
525 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset()); | 536 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset()); |
526 } | 537 } |
527 return; | 538 return; |
528 } | 539 } |
529 } else if (instr == 0x68 && dst.is(eax)) { // push of immediate 32 bit | 540 } else if (instr == 0x68 && dst.is(eax)) { // push of immediate 32 bit |
530 // 68XXXXXXXX push 0xXXXXXXXX | 541 // 68XXXXXXXX push 0xXXXXXXXX |
531 // 58 pop eax | 542 // 58 pop eax |
532 last_pc_[0] = 0xb8; | 543 last_pc_[0] = 0xb8; |
533 last_pc_ = NULL; | 544 last_pc_ = NULL; |
534 // change to | 545 // change to |
535 // b8XXXXXXXX mov eax,0xXXXXXXXX | 546 // b8XXXXXXXX mov eax,0xXXXXXXXX |
536 if (FLAG_print_push_pop_elimination) { | 547 if (FLAG_print_peephole_optimization) { |
537 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset()); | 548 PrintF("%d push/pop (imm->reg) eliminated\n", pc_offset()); |
538 } | 549 } |
539 return; | 550 return; |
540 } | 551 } |
541 | 552 |
542 // Other potential patterns for peephole: | 553 // Other potential patterns for peephole: |
543 // 0x712716 102 890424 mov [esp], eax | 554 // 0x712716 102 890424 mov [esp], eax |
544 // 0x712719 105 8b1424 mov edx, [esp] | 555 // 0x712719 105 8b1424 mov edx, [esp] |
545 } | 556 } |
546 EnsureSpace ensure_space(this); | 557 EnsureSpace ensure_space(this); |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
769 | 780 |
770 | 781 |
771 void Assembler::rep_stos() { | 782 void Assembler::rep_stos() { |
772 EnsureSpace ensure_space(this); | 783 EnsureSpace ensure_space(this); |
773 last_pc_ = pc_; | 784 last_pc_ = pc_; |
774 EMIT(0xF3); | 785 EMIT(0xF3); |
775 EMIT(0xAB); | 786 EMIT(0xAB); |
776 } | 787 } |
777 | 788 |
778 | 789 |
| 790 void Assembler::stos() { |
| 791 EnsureSpace ensure_space(this); |
| 792 last_pc_ = pc_; |
| 793 EMIT(0xAB); |
| 794 } |
| 795 |
| 796 |
779 void Assembler::xchg(Register dst, Register src) { | 797 void Assembler::xchg(Register dst, Register src) { |
780 EnsureSpace ensure_space(this); | 798 EnsureSpace ensure_space(this); |
781 last_pc_ = pc_; | 799 last_pc_ = pc_; |
782 if (src.is(eax) || dst.is(eax)) { // Single-byte encoding. | 800 if (src.is(eax) || dst.is(eax)) { // Single-byte encoding. |
783 EMIT(0x90 | (src.is(eax) ? dst.code() : src.code())); | 801 EMIT(0x90 | (src.is(eax) ? dst.code() : src.code())); |
784 } else { | 802 } else { |
785 EMIT(0x87); | 803 EMIT(0x87); |
786 EMIT(0xC0 | src.code() << 3 | dst.code()); | 804 EMIT(0xC0 | src.code() << 3 | dst.code()); |
787 } | 805 } |
788 } | 806 } |
(...skipping 17 matching lines...) Expand all Loading... |
806 void Assembler::add(Register dst, const Operand& src) { | 824 void Assembler::add(Register dst, const Operand& src) { |
807 EnsureSpace ensure_space(this); | 825 EnsureSpace ensure_space(this); |
808 last_pc_ = pc_; | 826 last_pc_ = pc_; |
809 EMIT(0x03); | 827 EMIT(0x03); |
810 emit_operand(dst, src); | 828 emit_operand(dst, src); |
811 } | 829 } |
812 | 830 |
813 | 831 |
814 void Assembler::add(const Operand& dst, const Immediate& x) { | 832 void Assembler::add(const Operand& dst, const Immediate& x) { |
815 ASSERT(reloc_info_writer.last_pc() != NULL); | 833 ASSERT(reloc_info_writer.last_pc() != NULL); |
816 if (FLAG_push_pop_elimination && (reloc_info_writer.last_pc() <= last_pc_)) { | 834 if (FLAG_peephole_optimization && (reloc_info_writer.last_pc() <= last_pc_)) { |
817 byte instr = last_pc_[0]; | 835 byte instr = last_pc_[0]; |
818 if ((instr & 0xf8) == 0x50) { | 836 if ((instr & 0xf8) == 0x50) { |
819 // Last instruction was a push. Check whether this is a pop without a | 837 // Last instruction was a push. Check whether this is a pop without a |
820 // result. | 838 // result. |
821 if ((dst.is_reg(esp)) && | 839 if ((dst.is_reg(esp)) && |
822 (x.x_ == kPointerSize) && (x.rmode_ == RelocInfo::NONE)) { | 840 (x.x_ == kPointerSize) && (x.rmode_ == RelocInfo::NONE)) { |
823 pc_ = last_pc_; | 841 pc_ = last_pc_; |
824 last_pc_ = NULL; | 842 last_pc_ = NULL; |
825 if (FLAG_print_push_pop_elimination) { | 843 if (FLAG_print_peephole_optimization) { |
826 PrintF("%d push/pop(noreg) eliminated\n", pc_offset()); | 844 PrintF("%d push/pop(noreg) eliminated\n", pc_offset()); |
827 } | 845 } |
828 return; | 846 return; |
829 } | 847 } |
830 } | 848 } |
831 } | 849 } |
832 EnsureSpace ensure_space(this); | 850 EnsureSpace ensure_space(this); |
833 last_pc_ = pc_; | 851 last_pc_ = pc_; |
834 emit_arith(0, dst, x); | 852 emit_arith(0, dst, x); |
835 } | 853 } |
(...skipping 1685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2521 push_insn[1] = 13; // Skip over coverage insns. | 2539 push_insn[1] = 13; // Skip over coverage insns. |
2522 if (coverage_log != NULL) { | 2540 if (coverage_log != NULL) { |
2523 fprintf(coverage_log, "%s\n", file_line); | 2541 fprintf(coverage_log, "%s\n", file_line); |
2524 fflush(coverage_log); | 2542 fflush(coverage_log); |
2525 } | 2543 } |
2526 } | 2544 } |
2527 | 2545 |
2528 #endif | 2546 #endif |
2529 | 2547 |
2530 } } // namespace v8::internal | 2548 } } // namespace v8::internal |
| 2549 |
| 2550 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |