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