Chromium Code Reviews| 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 |