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 are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // 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 655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
666 Instr instr = instr_at(pos); | 666 Instr instr = instr_at(pos); |
667 if ((instr & ~kImm16Mask) == 0) { | 667 if ((instr & ~kImm16Mask) == 0) { |
668 // Emitted label constant, not part of a branch. | 668 // Emitted label constant, not part of a branch. |
669 if (instr == 0) { | 669 if (instr == 0) { |
670 return kEndOfChain; | 670 return kEndOfChain; |
671 } else { | 671 } else { |
672 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; | 672 int32_t imm18 =((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; |
673 return (imm18 + pos); | 673 return (imm18 + pos); |
674 } | 674 } |
675 } | 675 } |
676 // Check we have a branch or jump instruction. | |
677 DCHECK(IsBranch(instr) || IsJ(instr) || IsLui(instr)); | |
678 // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming | 676 // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming |
679 // the compiler uses arithmectic shifts for signed integers. | 677 // the compiler uses arithmectic shifts for signed integers. |
680 if (IsBranch(instr)) { | 678 if (IsBranch(instr)) { |
681 int32_t imm18 = ((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; | 679 int32_t imm18 = ((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; |
682 | 680 |
683 if (imm18 == kEndOfChain) { | 681 if (imm18 == kEndOfChain) { |
684 // EndOfChain sentinel is returned directly, not relative to pc or pos. | 682 // EndOfChain sentinel is returned directly, not relative to pc or pos. |
685 return kEndOfChain; | 683 return kEndOfChain; |
686 } else { | 684 } else { |
687 return pos + kBranchPCOffset + imm18; | 685 return pos + kBranchPCOffset + imm18; |
688 } | 686 } |
689 } else if (IsLui(instr)) { | 687 } else if (IsLui(instr)) { |
690 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize); | 688 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize); |
691 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); | 689 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); |
692 DCHECK(IsOri(instr_ori)); | 690 DCHECK(IsOri(instr_ori)); |
693 int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift; | 691 int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift; |
694 imm |= (instr_ori & static_cast<int32_t>(kImm16Mask)); | 692 imm |= (instr_ori & static_cast<int32_t>(kImm16Mask)); |
695 | 693 |
696 if (imm == kEndOfJumpChain) { | 694 if (imm == kEndOfJumpChain) { |
697 // EndOfChain sentinel is returned directly, not relative to pc or pos. | 695 // EndOfChain sentinel is returned directly, not relative to pc or pos. |
698 return kEndOfChain; | 696 return kEndOfChain; |
699 } else { | 697 } else { |
700 uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); | 698 uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); |
701 int32_t delta = instr_address - imm; | 699 int32_t delta = instr_address - imm; |
702 DCHECK(pos > delta); | 700 DCHECK(pos > delta); |
703 return pos - delta; | 701 return pos - delta; |
704 } | 702 } |
705 } else { | 703 } else if (IsJ(instr)) { |
706 int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; | 704 int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; |
707 if (imm28 == kEndOfJumpChain) { | 705 if (imm28 == kEndOfJumpChain) { |
708 // EndOfChain sentinel is returned directly, not relative to pc or pos. | 706 // EndOfChain sentinel is returned directly, not relative to pc or pos. |
709 return kEndOfChain; | 707 return kEndOfChain; |
710 } else { | 708 } else { |
711 uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); | 709 uint32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos); |
712 instr_address &= kImm28Mask; | 710 instr_address &= kImm28Mask; |
713 int32_t delta = instr_address - imm28; | 711 int32_t delta = instr_address - imm28; |
714 DCHECK(pos > delta); | 712 DCHECK(pos > delta); |
715 return pos - delta; | 713 return pos - delta; |
716 } | 714 } |
| 715 } else { // IsLabel(instr) |
| 716 int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; |
| 717 if (imm28 == kEndOfJumpChain) { |
| 718 // EndOfChain sentinel is returned directly, not relative to pc or pos. |
| 719 return kEndOfChain; |
| 720 } else { |
| 721 return pos + imm28; |
| 722 } |
717 } | 723 } |
718 } | 724 } |
719 | 725 |
720 | 726 |
721 void Assembler::target_at_put(int32_t pos, int32_t target_pos) { | 727 void Assembler::target_at_put(int32_t pos, int32_t target_pos) { |
722 Instr instr = instr_at(pos); | 728 Instr instr = instr_at(pos); |
723 if ((instr & ~kImm16Mask) == 0) { | 729 if ((instr & ~kImm16Mask) == 0) { |
724 DCHECK(target_pos == kEndOfChain || target_pos >= 0); | 730 DCHECK(target_pos == kEndOfChain || target_pos >= 0); |
725 // Emitted label constant, not part of a branch. | 731 // Emitted label constant, not part of a branch. |
726 // Make label relative to Code* of generated Code object. | 732 // Make label relative to Code* of generated Code object. |
727 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); | 733 instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); |
728 return; | 734 return; |
729 } | 735 } |
730 | 736 |
731 DCHECK(IsBranch(instr) || IsJ(instr) || IsLui(instr)); | |
732 if (IsBranch(instr)) { | 737 if (IsBranch(instr)) { |
733 int32_t imm18 = target_pos - (pos + kBranchPCOffset); | 738 int32_t imm18 = target_pos - (pos + kBranchPCOffset); |
734 DCHECK((imm18 & 3) == 0); | 739 DCHECK((imm18 & 3) == 0); |
735 | 740 |
736 instr &= ~kImm16Mask; | 741 instr &= ~kImm16Mask; |
737 int32_t imm16 = imm18 >> 2; | 742 int32_t imm16 = imm18 >> 2; |
738 DCHECK(is_int16(imm16)); | 743 DCHECK(is_int16(imm16)); |
739 | 744 |
740 instr_at_put(pos, instr | (imm16 & kImm16Mask)); | 745 instr_at_put(pos, instr | (imm16 & kImm16Mask)); |
741 } else if (IsLui(instr)) { | 746 } else if (IsLui(instr)) { |
742 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize); | 747 Instr instr_lui = instr_at(pos + 0 * Assembler::kInstrSize); |
743 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); | 748 Instr instr_ori = instr_at(pos + 1 * Assembler::kInstrSize); |
744 DCHECK(IsOri(instr_ori)); | 749 DCHECK(IsOri(instr_ori)); |
745 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos; | 750 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos; |
746 DCHECK((imm & 3) == 0); | 751 DCHECK((imm & 3) == 0); |
747 | 752 |
748 instr_lui &= ~kImm16Mask; | 753 instr_lui &= ~kImm16Mask; |
749 instr_ori &= ~kImm16Mask; | 754 instr_ori &= ~kImm16Mask; |
750 | 755 |
751 instr_at_put(pos + 0 * Assembler::kInstrSize, | 756 instr_at_put(pos + 0 * Assembler::kInstrSize, |
752 instr_lui | ((imm & kHiMask) >> kLuiShift)); | 757 instr_lui | ((imm & kHiMask) >> kLuiShift)); |
753 instr_at_put(pos + 1 * Assembler::kInstrSize, | 758 instr_at_put(pos + 1 * Assembler::kInstrSize, |
754 instr_ori | (imm & kImm16Mask)); | 759 instr_ori | (imm & kImm16Mask)); |
755 } else { | 760 } else if (IsJ(instr)) { |
756 uint32_t imm28 = reinterpret_cast<uint32_t>(buffer_) + target_pos; | 761 uint32_t imm28 = reinterpret_cast<uint32_t>(buffer_) + target_pos; |
757 imm28 &= kImm28Mask; | 762 imm28 &= kImm28Mask; |
758 DCHECK((imm28 & 3) == 0); | 763 DCHECK((imm28 & 3) == 0); |
759 | 764 |
760 instr &= ~kImm26Mask; | 765 instr &= ~kImm26Mask; |
761 uint32_t imm26 = imm28 >> 2; | 766 uint32_t imm26 = imm28 >> 2; |
762 DCHECK(is_uint26(imm26)); | 767 DCHECK(is_uint26(imm26)); |
763 | 768 |
764 instr_at_put(pos, instr | (imm26 & kImm26Mask)); | 769 instr_at_put(pos, instr | (imm26 & kImm26Mask)); |
| 770 } else { |
| 771 uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos; |
| 772 instr_at_put(pos, imm); |
765 } | 773 } |
766 } | 774 } |
767 | 775 |
768 | 776 |
769 void Assembler::print(Label* L) { | 777 void Assembler::print(Label* L) { |
770 if (L->is_unused()) { | 778 if (L->is_unused()) { |
771 PrintF("unused label\n"); | 779 PrintF("unused label\n"); |
772 } else if (L->is_bound()) { | 780 } else if (L->is_bound()) { |
773 PrintF("bound label to %d\n", L->pos()); | 781 PrintF("bound label to %d\n", L->pos()); |
774 } else if (L->is_linked()) { | 782 } else if (L->is_linked()) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
809 trampoline_pos = get_trampoline_entry(fixup_pos); | 817 trampoline_pos = get_trampoline_entry(fixup_pos); |
810 CHECK(trampoline_pos != kInvalidSlotPos); | 818 CHECK(trampoline_pos != kInvalidSlotPos); |
811 } | 819 } |
812 DCHECK((trampoline_pos - fixup_pos) <= kMaxBranchOffset); | 820 DCHECK((trampoline_pos - fixup_pos) <= kMaxBranchOffset); |
813 target_at_put(fixup_pos, trampoline_pos); | 821 target_at_put(fixup_pos, trampoline_pos); |
814 fixup_pos = trampoline_pos; | 822 fixup_pos = trampoline_pos; |
815 dist = pos - fixup_pos; | 823 dist = pos - fixup_pos; |
816 } | 824 } |
817 target_at_put(fixup_pos, pos); | 825 target_at_put(fixup_pos, pos); |
818 } else { | 826 } else { |
819 DCHECK(IsJ(instr) || IsLui(instr) || IsEmittedConstant(instr)); | |
820 target_at_put(fixup_pos, pos); | 827 target_at_put(fixup_pos, pos); |
821 } | 828 } |
822 } | 829 } |
823 L->bind_to(pos); | 830 L->bind_to(pos); |
824 | 831 |
825 // Keep track of the last bound label so we don't eliminate any instructions | 832 // Keep track of the last bound label so we don't eliminate any instructions |
826 // before a bound label. | 833 // before a bound label. |
827 if (pos > last_bound_pos_) | 834 if (pos > last_bound_pos_) |
828 last_bound_pos_ = pos; | 835 last_bound_pos_ = pos; |
829 } | 836 } |
(...skipping 1521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2351 if (FLAG_trace_deopt) { | 2358 if (FLAG_trace_deopt) { |
2352 EnsureSpace ensure_space(this); | 2359 EnsureSpace ensure_space(this); |
2353 RecordRelocInfo(RelocInfo::POSITION, raw_position); | 2360 RecordRelocInfo(RelocInfo::POSITION, raw_position); |
2354 RecordRelocInfo(RelocInfo::DEOPT_REASON, reason); | 2361 RecordRelocInfo(RelocInfo::DEOPT_REASON, reason); |
2355 } | 2362 } |
2356 } | 2363 } |
2357 | 2364 |
2358 | 2365 |
2359 int Assembler::RelocateInternalReference(byte* pc, intptr_t pc_delta) { | 2366 int Assembler::RelocateInternalReference(byte* pc, intptr_t pc_delta) { |
2360 Instr instr = instr_at(pc); | 2367 Instr instr = instr_at(pc); |
2361 DCHECK(IsJ(instr) || IsLui(instr)); | |
2362 if (IsLui(instr)) { | 2368 if (IsLui(instr)) { |
2363 Instr instr_lui = instr_at(pc + 0 * Assembler::kInstrSize); | 2369 Instr instr_lui = instr_at(pc + 0 * Assembler::kInstrSize); |
2364 Instr instr_ori = instr_at(pc + 1 * Assembler::kInstrSize); | 2370 Instr instr_ori = instr_at(pc + 1 * Assembler::kInstrSize); |
2365 DCHECK(IsOri(instr_ori)); | 2371 DCHECK(IsOri(instr_ori)); |
2366 int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift; | 2372 int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift; |
2367 imm |= (instr_ori & static_cast<int32_t>(kImm16Mask)); | 2373 imm |= (instr_ori & static_cast<int32_t>(kImm16Mask)); |
2368 if (imm == kEndOfJumpChain) { | 2374 if (imm == kEndOfJumpChain) { |
2369 return 0; // Number of instructions patched. | 2375 return 0; // Number of instructions patched. |
2370 } | 2376 } |
2371 imm += pc_delta; | 2377 imm += pc_delta; |
2372 DCHECK((imm & 3) == 0); | 2378 DCHECK((imm & 3) == 0); |
2373 | 2379 |
2374 instr_lui &= ~kImm16Mask; | 2380 instr_lui &= ~kImm16Mask; |
2375 instr_ori &= ~kImm16Mask; | 2381 instr_ori &= ~kImm16Mask; |
2376 | 2382 |
2377 instr_at_put(pc + 0 * Assembler::kInstrSize, | 2383 instr_at_put(pc + 0 * Assembler::kInstrSize, |
2378 instr_lui | ((imm >> kLuiShift) & kImm16Mask)); | 2384 instr_lui | ((imm >> kLuiShift) & kImm16Mask)); |
2379 instr_at_put(pc + 1 * Assembler::kInstrSize, | 2385 instr_at_put(pc + 1 * Assembler::kInstrSize, |
2380 instr_ori | (imm & kImm16Mask)); | 2386 instr_ori | (imm & kImm16Mask)); |
2381 return 2; // Number of instructions patched. | 2387 return 2; // Number of instructions patched. |
2382 } else { | 2388 } else if (IsJ(instr)) { |
2383 uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; | 2389 uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; |
2384 if (static_cast<int32_t>(imm28) == kEndOfJumpChain) { | 2390 if (static_cast<int32_t>(imm28) == kEndOfJumpChain) { |
2385 return 0; // Number of instructions patched. | 2391 return 0; // Number of instructions patched. |
2386 } | 2392 } |
2387 imm28 += pc_delta; | 2393 imm28 += pc_delta; |
2388 imm28 &= kImm28Mask; | 2394 imm28 &= kImm28Mask; |
2389 DCHECK((imm28 & 3) == 0); | 2395 DCHECK((imm28 & 3) == 0); |
2390 | 2396 |
2391 instr &= ~kImm26Mask; | 2397 instr &= ~kImm26Mask; |
2392 uint32_t imm26 = imm28 >> 2; | 2398 uint32_t imm26 = imm28 >> 2; |
2393 DCHECK(is_uint26(imm26)); | 2399 DCHECK(is_uint26(imm26)); |
2394 | 2400 |
2395 instr_at_put(pc, instr | (imm26 & kImm26Mask)); | 2401 instr_at_put(pc, instr | (imm26 & kImm26Mask)); |
2396 return 1; // Number of instructions patched. | 2402 return 1; // Number of instructions patched. |
| 2403 } else { // IsLabel(instr) |
| 2404 int32_t* p = reinterpret_cast<int32_t*>(pc); |
| 2405 uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; |
| 2406 if (static_cast<int32_t>(imm28) == kEndOfJumpChain) { |
| 2407 return 0; // Number of instructions patched. |
| 2408 } |
| 2409 *p += pc_delta; |
| 2410 return 1; // Number of instructions patched. |
2397 } | 2411 } |
2398 } | 2412 } |
2399 | 2413 |
2400 | 2414 |
2401 void Assembler::GrowBuffer() { | 2415 void Assembler::GrowBuffer() { |
2402 if (!own_buffer_) FATAL("external code buffer is too small"); | 2416 if (!own_buffer_) FATAL("external code buffer is too small"); |
2403 | 2417 |
2404 // Compute new buffer size. | 2418 // Compute new buffer size. |
2405 CodeDesc desc; // The new buffer. | 2419 CodeDesc desc; // The new buffer. |
2406 if (buffer_size_ < 1 * MB) { | 2420 if (buffer_size_ < 1 * MB) { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2451 } | 2465 } |
2452 | 2466 |
2453 | 2467 |
2454 void Assembler::dd(uint32_t data) { | 2468 void Assembler::dd(uint32_t data) { |
2455 CheckBuffer(); | 2469 CheckBuffer(); |
2456 *reinterpret_cast<uint32_t*>(pc_) = data; | 2470 *reinterpret_cast<uint32_t*>(pc_) = data; |
2457 pc_ += sizeof(uint32_t); | 2471 pc_ += sizeof(uint32_t); |
2458 } | 2472 } |
2459 | 2473 |
2460 | 2474 |
| 2475 void Assembler::dd(Label* label) { |
| 2476 CheckBuffer(); |
| 2477 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); |
| 2478 if (label->is_bound()) { |
| 2479 uint32_t data = reinterpret_cast<uint32_t>(buffer_ + label->pos()); |
| 2480 *reinterpret_cast<uint32_t*>(pc_) = data; |
| 2481 pc_ += sizeof(uint32_t); |
| 2482 } else { |
| 2483 int target_pos; |
| 2484 if (label->is_linked()) { |
| 2485 // Point to previous instruction that uses the link. |
| 2486 target_pos = label->pos(); |
| 2487 } else { |
| 2488 // First entry of the link chain points to itself. |
| 2489 target_pos = pc_offset(); |
| 2490 } |
| 2491 label->link_to(pc_offset()); |
| 2492 // Encode internal reference to unbound label. We set the least significant |
| 2493 // bit to distinguish unbound internal references in GrowBuffer() below. |
| 2494 int diff = target_pos - pc_offset(); |
| 2495 DCHECK_EQ(0, diff & 3); |
| 2496 int imm26 = diff >> 2; |
| 2497 DCHECK(is_int26(imm26)); |
| 2498 // Emit special LABEL instruction. |
| 2499 emit(LABEL | (imm26 & kImm26Mask)); |
| 2500 } |
| 2501 } |
| 2502 |
| 2503 |
2461 void Assembler::emit_code_stub_address(Code* stub) { | 2504 void Assembler::emit_code_stub_address(Code* stub) { |
2462 CheckBuffer(); | 2505 CheckBuffer(); |
2463 *reinterpret_cast<uint32_t*>(pc_) = | 2506 *reinterpret_cast<uint32_t*>(pc_) = |
2464 reinterpret_cast<uint32_t>(stub->instruction_start()); | 2507 reinterpret_cast<uint32_t>(stub->instruction_start()); |
2465 pc_ += sizeof(uint32_t); | 2508 pc_ += sizeof(uint32_t); |
2466 } | 2509 } |
2467 | 2510 |
2468 | 2511 |
2469 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { | 2512 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { |
2470 // We do not try to reuse pool constants. | 2513 // We do not try to reuse pool constants. |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2749 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) { | 2792 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) { |
2750 // No out-of-line constant pool support. | 2793 // No out-of-line constant pool support. |
2751 DCHECK(!FLAG_enable_ool_constant_pool); | 2794 DCHECK(!FLAG_enable_ool_constant_pool); |
2752 return; | 2795 return; |
2753 } | 2796 } |
2754 | 2797 |
2755 | 2798 |
2756 } } // namespace v8::internal | 2799 } } // namespace v8::internal |
2757 | 2800 |
2758 #endif // V8_TARGET_ARCH_MIPS | 2801 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |