| 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 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 | 320 |
| 321 // ----------------------------------------------------------------------------- | 321 // ----------------------------------------------------------------------------- |
| 322 // Implementation of RelocInfo | 322 // Implementation of RelocInfo |
| 323 | 323 |
| 324 // static | 324 // static |
| 325 const int RelocInfo::kApplyMask = 0; | 325 const int RelocInfo::kApplyMask = 0; |
| 326 | 326 |
| 327 | 327 |
| 328 bool RelocInfo::IsCodedSpecially() { | 328 bool RelocInfo::IsCodedSpecially() { |
| 329 // The deserializer needs to know whether a pointer is specially coded. Being | 329 // The deserializer needs to know whether a pointer is specially coded. Being |
| 330 // specially coded on ARM means that it is a movw/movt instruction, or is an | 330 // specially coded on ARM means that it is a movw/movt instruction. We don't |
| 331 // embedded constant pool entry. These only occur if | 331 // generate those for relocatable pointers. |
| 332 // FLAG_enable_embedded_constant_pool is true. | 332 return false; |
| 333 return FLAG_enable_embedded_constant_pool; | |
| 334 } | 333 } |
| 335 | 334 |
| 336 | 335 |
| 337 bool RelocInfo::IsInConstantPool() { | 336 bool RelocInfo::IsInConstantPool() { |
| 338 return Assembler::is_constant_pool_load(pc_); | 337 return Assembler::is_constant_pool_load(pc_); |
| 339 } | 338 } |
| 340 | 339 |
| 341 Address RelocInfo::wasm_memory_reference() { | 340 Address RelocInfo::wasm_memory_reference() { |
| 342 DCHECK(IsWasmMemoryReference(rmode_)); | 341 DCHECK(IsWasmMemoryReference(rmode_)); |
| 343 return Assembler::target_address_at(pc_, host_); | 342 return Assembler::target_address_at(pc_, host_); |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 496 // register r is not encoded. | 495 // register r is not encoded. |
| 497 const Instr kPushRegPattern = | 496 const Instr kPushRegPattern = |
| 498 al | B26 | 4 | NegPreIndex | Register::kCode_sp * B16; | 497 al | B26 | 4 | NegPreIndex | Register::kCode_sp * B16; |
| 499 // ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r)) | 498 // ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r)) |
| 500 // register r is not encoded. | 499 // register r is not encoded. |
| 501 const Instr kPopRegPattern = | 500 const Instr kPopRegPattern = |
| 502 al | B26 | L | 4 | PostIndex | Register::kCode_sp * B16; | 501 al | B26 | L | 4 | PostIndex | Register::kCode_sp * B16; |
| 503 // ldr rd, [pc, #offset] | 502 // ldr rd, [pc, #offset] |
| 504 const Instr kLdrPCImmedMask = 15 * B24 | 7 * B20 | 15 * B16; | 503 const Instr kLdrPCImmedMask = 15 * B24 | 7 * B20 | 15 * B16; |
| 505 const Instr kLdrPCImmedPattern = 5 * B24 | L | Register::kCode_pc * B16; | 504 const Instr kLdrPCImmedPattern = 5 * B24 | L | Register::kCode_pc * B16; |
| 506 // ldr rd, [pp, #offset] | |
| 507 const Instr kLdrPpImmedMask = 15 * B24 | 7 * B20 | 15 * B16; | |
| 508 const Instr kLdrPpImmedPattern = 5 * B24 | L | Register::kCode_r8 * B16; | |
| 509 // ldr rd, [pp, rn] | |
| 510 const Instr kLdrPpRegMask = 15 * B24 | 7 * B20 | 15 * B16; | |
| 511 const Instr kLdrPpRegPattern = 7 * B24 | L | Register::kCode_r8 * B16; | |
| 512 // vldr dd, [pc, #offset] | 505 // vldr dd, [pc, #offset] |
| 513 const Instr kVldrDPCMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8; | 506 const Instr kVldrDPCMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8; |
| 514 const Instr kVldrDPCPattern = 13 * B24 | L | Register::kCode_pc * B16 | 11 * B8; | 507 const Instr kVldrDPCPattern = 13 * B24 | L | Register::kCode_pc * B16 | 11 * B8; |
| 515 // vldr dd, [pp, #offset] | |
| 516 const Instr kVldrDPpMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8; | |
| 517 const Instr kVldrDPpPattern = 13 * B24 | L | Register::kCode_r8 * B16 | 11 * B8; | |
| 518 // blxcc rm | 508 // blxcc rm |
| 519 const Instr kBlxRegMask = | 509 const Instr kBlxRegMask = |
| 520 15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4; | 510 15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4; |
| 521 const Instr kBlxRegPattern = | 511 const Instr kBlxRegPattern = |
| 522 B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | BLX; | 512 B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | BLX; |
| 523 const Instr kBlxIp = al | kBlxRegPattern | ip.code(); | 513 const Instr kBlxIp = al | kBlxRegPattern | ip.code(); |
| 524 const Instr kMovMvnMask = 0x6d * B21 | 0xf * B16; | 514 const Instr kMovMvnMask = 0x6d * B21 | 0xf * B16; |
| 525 const Instr kMovMvnPattern = 0xd * B21; | 515 const Instr kMovMvnPattern = 0xd * B21; |
| 526 const Instr kMovMvnFlip = B22; | 516 const Instr kMovMvnFlip = B22; |
| 527 const Instr kMovLeaveCCMask = 0xdff * B16; | 517 const Instr kMovLeaveCCMask = 0xdff * B16; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 547 const Instr kLdrRegFpNegOffsetPattern = | 537 const Instr kLdrRegFpNegOffsetPattern = |
| 548 al | B26 | L | NegOffset | Register::kCode_fp * B16; | 538 al | B26 | L | NegOffset | Register::kCode_fp * B16; |
| 549 const Instr kStrRegFpNegOffsetPattern = | 539 const Instr kStrRegFpNegOffsetPattern = |
| 550 al | B26 | NegOffset | Register::kCode_fp * B16; | 540 al | B26 | NegOffset | Register::kCode_fp * B16; |
| 551 const Instr kLdrStrInstrTypeMask = 0xffff0000; | 541 const Instr kLdrStrInstrTypeMask = 0xffff0000; |
| 552 | 542 |
| 553 Assembler::Assembler(IsolateData isolate_data, void* buffer, int buffer_size) | 543 Assembler::Assembler(IsolateData isolate_data, void* buffer, int buffer_size) |
| 554 : AssemblerBase(isolate_data, buffer, buffer_size), | 544 : AssemblerBase(isolate_data, buffer, buffer_size), |
| 555 recorded_ast_id_(TypeFeedbackId::None()), | 545 recorded_ast_id_(TypeFeedbackId::None()), |
| 556 pending_32_bit_constants_(), | 546 pending_32_bit_constants_(), |
| 557 pending_64_bit_constants_(), | 547 pending_64_bit_constants_() { |
| 558 constant_pool_builder_(kLdrMaxReachBits, kVldrMaxReachBits) { | |
| 559 pending_32_bit_constants_.reserve(kMinNumPendingConstants); | 548 pending_32_bit_constants_.reserve(kMinNumPendingConstants); |
| 560 pending_64_bit_constants_.reserve(kMinNumPendingConstants); | 549 pending_64_bit_constants_.reserve(kMinNumPendingConstants); |
| 561 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_); | 550 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_); |
| 562 next_buffer_check_ = 0; | 551 next_buffer_check_ = 0; |
| 563 const_pool_blocked_nesting_ = 0; | 552 const_pool_blocked_nesting_ = 0; |
| 564 no_const_pool_before_ = 0; | 553 no_const_pool_before_ = 0; |
| 565 first_const_pool_32_use_ = -1; | 554 first_const_pool_32_use_ = -1; |
| 566 first_const_pool_64_use_ = -1; | 555 first_const_pool_64_use_ = -1; |
| 567 last_bound_pos_ = 0; | 556 last_bound_pos_ = 0; |
| 568 ClearRecordedAstId(); | 557 ClearRecordedAstId(); |
| 569 if (CpuFeatures::IsSupported(VFP32DREGS)) { | 558 if (CpuFeatures::IsSupported(VFP32DREGS)) { |
| 570 // Register objects tend to be abstracted and survive between scopes, so | 559 // Register objects tend to be abstracted and survive between scopes, so |
| 571 // it's awkward to use CpuFeatures::VFP32DREGS with CpuFeatureScope. To make | 560 // it's awkward to use CpuFeatures::VFP32DREGS with CpuFeatureScope. To make |
| 572 // its use consistent with other features, we always enable it if we can. | 561 // its use consistent with other features, we always enable it if we can. |
| 573 EnableCpuFeature(VFP32DREGS); | 562 EnableCpuFeature(VFP32DREGS); |
| 574 } | 563 } |
| 575 } | 564 } |
| 576 | 565 |
| 577 | 566 |
| 578 Assembler::~Assembler() { | 567 Assembler::~Assembler() { |
| 579 DCHECK(const_pool_blocked_nesting_ == 0); | 568 DCHECK(const_pool_blocked_nesting_ == 0); |
| 580 } | 569 } |
| 581 | 570 |
| 582 | 571 |
| 583 void Assembler::GetCode(CodeDesc* desc) { | 572 void Assembler::GetCode(CodeDesc* desc) { |
| 584 // Emit constant pool if necessary. | 573 // Emit constant pool if necessary. |
| 585 int constant_pool_offset = 0; | 574 int constant_pool_offset = 0; |
| 586 if (FLAG_enable_embedded_constant_pool) { | 575 CheckConstPool(true, false); |
| 587 constant_pool_offset = EmitEmbeddedConstantPool(); | 576 DCHECK(pending_32_bit_constants_.empty()); |
| 588 } else { | 577 DCHECK(pending_64_bit_constants_.empty()); |
| 589 CheckConstPool(true, false); | |
| 590 DCHECK(pending_32_bit_constants_.empty()); | |
| 591 DCHECK(pending_64_bit_constants_.empty()); | |
| 592 } | |
| 593 // Set up code descriptor. | 578 // Set up code descriptor. |
| 594 desc->buffer = buffer_; | 579 desc->buffer = buffer_; |
| 595 desc->buffer_size = buffer_size_; | 580 desc->buffer_size = buffer_size_; |
| 596 desc->instr_size = pc_offset(); | 581 desc->instr_size = pc_offset(); |
| 597 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); | 582 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); |
| 598 desc->constant_pool_size = | 583 desc->constant_pool_size = |
| 599 (constant_pool_offset ? desc->instr_size - constant_pool_offset : 0); | 584 (constant_pool_offset ? desc->instr_size - constant_pool_offset : 0); |
| 600 desc->origin = this; | 585 desc->origin = this; |
| 601 desc->unwinding_info_size = 0; | 586 desc->unwinding_info_size = 0; |
| 602 desc->unwinding_info = nullptr; | 587 desc->unwinding_info = nullptr; |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 733 } | 718 } |
| 734 | 719 |
| 735 | 720 |
| 736 Register Assembler::GetRm(Instr instr) { | 721 Register Assembler::GetRm(Instr instr) { |
| 737 Register reg; | 722 Register reg; |
| 738 reg.reg_code = Instruction::RmValue(instr); | 723 reg.reg_code = Instruction::RmValue(instr); |
| 739 return reg; | 724 return reg; |
| 740 } | 725 } |
| 741 | 726 |
| 742 | 727 |
| 743 Instr Assembler::GetConsantPoolLoadPattern() { | |
| 744 if (FLAG_enable_embedded_constant_pool) { | |
| 745 return kLdrPpImmedPattern; | |
| 746 } else { | |
| 747 return kLdrPCImmedPattern; | |
| 748 } | |
| 749 } | |
| 750 | |
| 751 | |
| 752 Instr Assembler::GetConsantPoolLoadMask() { | |
| 753 if (FLAG_enable_embedded_constant_pool) { | |
| 754 return kLdrPpImmedMask; | |
| 755 } else { | |
| 756 return kLdrPCImmedMask; | |
| 757 } | |
| 758 } | |
| 759 | |
| 760 | |
| 761 bool Assembler::IsPush(Instr instr) { | 728 bool Assembler::IsPush(Instr instr) { |
| 762 return ((instr & ~kRdMask) == kPushRegPattern); | 729 return ((instr & ~kRdMask) == kPushRegPattern); |
| 763 } | 730 } |
| 764 | 731 |
| 765 | 732 |
| 766 bool Assembler::IsPop(Instr instr) { | 733 bool Assembler::IsPop(Instr instr) { |
| 767 return ((instr & ~kRdMask) == kPopRegPattern); | 734 return ((instr & ~kRdMask) == kPopRegPattern); |
| 768 } | 735 } |
| 769 | 736 |
| 770 | 737 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 788 } | 755 } |
| 789 | 756 |
| 790 | 757 |
| 791 bool Assembler::IsLdrPcImmediateOffset(Instr instr) { | 758 bool Assembler::IsLdrPcImmediateOffset(Instr instr) { |
| 792 // Check the instruction is indeed a | 759 // Check the instruction is indeed a |
| 793 // ldr<cond> <Rd>, [pc +/- offset_12]. | 760 // ldr<cond> <Rd>, [pc +/- offset_12]. |
| 794 return (instr & kLdrPCImmedMask) == kLdrPCImmedPattern; | 761 return (instr & kLdrPCImmedMask) == kLdrPCImmedPattern; |
| 795 } | 762 } |
| 796 | 763 |
| 797 | 764 |
| 798 bool Assembler::IsLdrPpImmediateOffset(Instr instr) { | |
| 799 // Check the instruction is indeed a | |
| 800 // ldr<cond> <Rd>, [pp +/- offset_12]. | |
| 801 return (instr & kLdrPpImmedMask) == kLdrPpImmedPattern; | |
| 802 } | |
| 803 | |
| 804 | |
| 805 bool Assembler::IsLdrPpRegOffset(Instr instr) { | |
| 806 // Check the instruction is indeed a | |
| 807 // ldr<cond> <Rd>, [pp, +/- <Rm>]. | |
| 808 return (instr & kLdrPpRegMask) == kLdrPpRegPattern; | |
| 809 } | |
| 810 | |
| 811 | |
| 812 Instr Assembler::GetLdrPpRegOffsetPattern() { return kLdrPpRegPattern; } | |
| 813 | |
| 814 | |
| 815 bool Assembler::IsVldrDPcImmediateOffset(Instr instr) { | 765 bool Assembler::IsVldrDPcImmediateOffset(Instr instr) { |
| 816 // Check the instruction is indeed a | 766 // Check the instruction is indeed a |
| 817 // vldr<cond> <Dd>, [pc +/- offset_10]. | 767 // vldr<cond> <Dd>, [pc +/- offset_10]. |
| 818 return (instr & kVldrDPCMask) == kVldrDPCPattern; | 768 return (instr & kVldrDPCMask) == kVldrDPCPattern; |
| 819 } | 769 } |
| 820 | 770 |
| 821 | 771 |
| 822 bool Assembler::IsVldrDPpImmediateOffset(Instr instr) { | |
| 823 // Check the instruction is indeed a | |
| 824 // vldr<cond> <Dd>, [pp +/- offset_10]. | |
| 825 return (instr & kVldrDPpMask) == kVldrDPpPattern; | |
| 826 } | |
| 827 | |
| 828 | |
| 829 bool Assembler::IsBlxReg(Instr instr) { | 772 bool Assembler::IsBlxReg(Instr instr) { |
| 830 // Check the instruction is indeed a | 773 // Check the instruction is indeed a |
| 831 // blxcc <Rm> | 774 // blxcc <Rm> |
| 832 return (instr & kBlxRegMask) == kBlxRegPattern; | 775 return (instr & kBlxRegMask) == kBlxRegPattern; |
| 833 } | 776 } |
| 834 | 777 |
| 835 | 778 |
| 836 bool Assembler::IsBlxIp(Instr instr) { | 779 bool Assembler::IsBlxIp(Instr instr) { |
| 837 // Check the instruction is indeed a | 780 // Check the instruction is indeed a |
| 838 // blx ip | 781 // blx ip |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1162 } else if (RelocInfo::IsNone(rmode_)) { | 1105 } else if (RelocInfo::IsNone(rmode_)) { |
| 1163 return false; | 1106 return false; |
| 1164 } | 1107 } |
| 1165 return true; | 1108 return true; |
| 1166 } | 1109 } |
| 1167 | 1110 |
| 1168 | 1111 |
| 1169 static bool use_mov_immediate_load(const Operand& x, | 1112 static bool use_mov_immediate_load(const Operand& x, |
| 1170 const Assembler* assembler) { | 1113 const Assembler* assembler) { |
| 1171 DCHECK(assembler != nullptr); | 1114 DCHECK(assembler != nullptr); |
| 1172 if (FLAG_enable_embedded_constant_pool && | 1115 if (x.must_output_reloc_info(assembler)) { |
| 1173 !assembler->is_constant_pool_available()) { | |
| 1174 return true; | |
| 1175 } else if (x.must_output_reloc_info(assembler)) { | |
| 1176 // Prefer constant pool if data is likely to be patched. | 1116 // Prefer constant pool if data is likely to be patched. |
| 1177 return false; | 1117 return false; |
| 1178 } else { | 1118 } else { |
| 1179 // Otherwise, use immediate load if movw / movt is available. | 1119 // Otherwise, use immediate load if movw / movt is available. |
| 1180 return CpuFeatures::IsSupported(ARMv7); | 1120 return CpuFeatures::IsSupported(ARMv7); |
| 1181 } | 1121 } |
| 1182 } | 1122 } |
| 1183 | 1123 |
| 1184 | 1124 |
| 1185 int Operand::instructions_required(const Assembler* assembler, | 1125 int Operand::instructions_required(const Assembler* assembler, |
| 1186 Instr instr) const { | 1126 Instr instr) const { |
| 1187 DCHECK(assembler != nullptr); | 1127 DCHECK(assembler != nullptr); |
| 1188 if (rm_.is_valid()) return 1; | 1128 if (rm_.is_valid()) return 1; |
| 1189 uint32_t dummy1, dummy2; | 1129 uint32_t dummy1, dummy2; |
| 1190 if (must_output_reloc_info(assembler) || | 1130 if (must_output_reloc_info(assembler) || |
| 1191 !fits_shifter(imm32_, &dummy1, &dummy2, &instr)) { | 1131 !fits_shifter(imm32_, &dummy1, &dummy2, &instr)) { |
| 1192 // The immediate operand cannot be encoded as a shifter operand, or use of | 1132 // The immediate operand cannot be encoded as a shifter operand, or use of |
| 1193 // constant pool is required. First account for the instructions required | 1133 // constant pool is required. First account for the instructions required |
| 1194 // for the constant pool or immediate load | 1134 // for the constant pool or immediate load |
| 1195 int instructions; | 1135 int instructions; |
| 1196 if (use_mov_immediate_load(*this, assembler)) { | 1136 if (use_mov_immediate_load(*this, assembler)) { |
| 1197 // A movw / movt or mov / orr immediate load. | 1137 // A movw / movt or mov / orr immediate load. |
| 1198 instructions = CpuFeatures::IsSupported(ARMv7) ? 2 : 4; | 1138 instructions = CpuFeatures::IsSupported(ARMv7) ? 2 : 4; |
| 1199 } else if (assembler->ConstantPoolAccessIsInOverflow()) { | |
| 1200 // An overflowed constant pool load. | |
| 1201 instructions = CpuFeatures::IsSupported(ARMv7) ? 3 : 5; | |
| 1202 } else { | 1139 } else { |
| 1203 // A small constant pool load. | 1140 // A small constant pool load. |
| 1204 instructions = 1; | 1141 instructions = 1; |
| 1205 } | 1142 } |
| 1206 | |
| 1207 if ((instr & ~kCondMask) != 13 * B21) { // mov, S not set | 1143 if ((instr & ~kCondMask) != 13 * B21) { // mov, S not set |
| 1208 // For a mov or mvn instruction which doesn't set the condition | 1144 // For a mov or mvn instruction which doesn't set the condition |
| 1209 // code, the constant pool or immediate load is enough, otherwise we need | 1145 // code, the constant pool or immediate load is enough, otherwise we need |
| 1210 // to account for the actual instruction being requested. | 1146 // to account for the actual instruction being requested. |
| 1211 instructions += 1; | 1147 instructions += 1; |
| 1212 } | 1148 } |
| 1213 return instructions; | 1149 return instructions; |
| 1214 } else { | 1150 } else { |
| 1215 // No use of constant pool and the immediate operand can be encoded as a | 1151 // No use of constant pool and the immediate operand can be encoded as a |
| 1216 // shifter operand. | 1152 // shifter operand. |
| 1217 return 1; | 1153 return 1; |
| 1218 } | 1154 } |
| 1219 } | 1155 } |
| 1220 | 1156 |
| 1221 | 1157 |
| 1222 void Assembler::move_32_bit_immediate(Register rd, | 1158 void Assembler::move_32_bit_immediate(Register rd, |
| 1223 const Operand& x, | 1159 const Operand& x, |
| 1224 Condition cond) { | 1160 Condition cond) { |
| 1225 uint32_t imm32 = static_cast<uint32_t>(x.imm32_); | 1161 uint32_t imm32 = static_cast<uint32_t>(x.imm32_); |
| 1226 if (x.must_output_reloc_info(this)) { | 1162 if (x.must_output_reloc_info(this)) { |
| 1227 RecordRelocInfo(x.rmode_); | 1163 RecordRelocInfo(x.rmode_); |
| 1228 } | 1164 } |
| 1229 | 1165 |
| 1230 if (use_mov_immediate_load(x, this)) { | 1166 if (use_mov_immediate_load(x, this)) { |
| 1167 // use_mov_immediate_load should return false when we need to output |
| 1168 // relocation info, since we prefer the constant pool for values that |
| 1169 // can be patched. |
| 1170 DCHECK(!x.must_output_reloc_info(this)); |
| 1231 Register target = rd.code() == pc.code() ? ip : rd; | 1171 Register target = rd.code() == pc.code() ? ip : rd; |
| 1232 if (CpuFeatures::IsSupported(ARMv7)) { | 1172 if (CpuFeatures::IsSupported(ARMv7)) { |
| 1233 CpuFeatureScope scope(this, ARMv7); | 1173 CpuFeatureScope scope(this, ARMv7); |
| 1234 if (!FLAG_enable_embedded_constant_pool && | |
| 1235 x.must_output_reloc_info(this)) { | |
| 1236 // Make sure the movw/movt doesn't get separated. | |
| 1237 BlockConstPoolFor(2); | |
| 1238 } | |
| 1239 movw(target, imm32 & 0xffff, cond); | 1174 movw(target, imm32 & 0xffff, cond); |
| 1240 movt(target, imm32 >> 16, cond); | 1175 movt(target, imm32 >> 16, cond); |
| 1241 } else { | |
| 1242 DCHECK(FLAG_enable_embedded_constant_pool); | |
| 1243 mov(target, Operand(imm32 & kImm8Mask), LeaveCC, cond); | |
| 1244 orr(target, target, Operand(imm32 & (kImm8Mask << 8)), LeaveCC, cond); | |
| 1245 orr(target, target, Operand(imm32 & (kImm8Mask << 16)), LeaveCC, cond); | |
| 1246 orr(target, target, Operand(imm32 & (kImm8Mask << 24)), LeaveCC, cond); | |
| 1247 } | 1176 } |
| 1248 if (target.code() != rd.code()) { | 1177 if (target.code() != rd.code()) { |
| 1249 mov(rd, target, LeaveCC, cond); | 1178 mov(rd, target, LeaveCC, cond); |
| 1250 } | 1179 } |
| 1251 } else { | 1180 } else { |
| 1252 DCHECK(!FLAG_enable_embedded_constant_pool || is_constant_pool_available()); | |
| 1253 ConstantPoolEntry::Access access = | 1181 ConstantPoolEntry::Access access = |
| 1254 ConstantPoolAddEntry(pc_offset(), x.rmode_, x.imm32_); | 1182 ConstantPoolAddEntry(pc_offset(), x.rmode_, x.imm32_); |
| 1255 if (access == ConstantPoolEntry::OVERFLOWED) { | 1183 DCHECK(access == ConstantPoolEntry::REGULAR); |
| 1256 DCHECK(FLAG_enable_embedded_constant_pool); | 1184 USE(access); |
| 1257 Register target = rd.code() == pc.code() ? ip : rd; | 1185 ldr(rd, MemOperand(pc, 0), cond); |
| 1258 // Emit instructions to load constant pool offset. | |
| 1259 if (CpuFeatures::IsSupported(ARMv7)) { | |
| 1260 CpuFeatureScope scope(this, ARMv7); | |
| 1261 movw(target, 0, cond); | |
| 1262 movt(target, 0, cond); | |
| 1263 } else { | |
| 1264 mov(target, Operand(0), LeaveCC, cond); | |
| 1265 orr(target, target, Operand(0), LeaveCC, cond); | |
| 1266 orr(target, target, Operand(0), LeaveCC, cond); | |
| 1267 orr(target, target, Operand(0), LeaveCC, cond); | |
| 1268 } | |
| 1269 // Load from constant pool at offset. | |
| 1270 ldr(rd, MemOperand(pp, target), cond); | |
| 1271 } else { | |
| 1272 DCHECK(access == ConstantPoolEntry::REGULAR); | |
| 1273 ldr(rd, MemOperand(FLAG_enable_embedded_constant_pool ? pp : pc, 0), | |
| 1274 cond); | |
| 1275 } | |
| 1276 } | 1186 } |
| 1277 } | 1187 } |
| 1278 | 1188 |
| 1279 | 1189 |
| 1280 void Assembler::addrmod1(Instr instr, | 1190 void Assembler::addrmod1(Instr instr, |
| 1281 Register rn, | 1191 Register rn, |
| 1282 Register rd, | 1192 Register rd, |
| 1283 const Operand& x) { | 1193 const Operand& x) { |
| 1284 CheckBuffer(); | 1194 CheckBuffer(); |
| 1285 DCHECK((instr & ~(kCondMask | kOpCodeMask | S)) == 0); | 1195 DCHECK((instr & ~(kCondMask | kOpCodeMask | S)) == 0); |
| (...skipping 1494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2780 } | 2690 } |
| 2781 } | 2691 } |
| 2782 | 2692 |
| 2783 | 2693 |
| 2784 void Assembler::vmov(const DwVfpRegister dst, | 2694 void Assembler::vmov(const DwVfpRegister dst, |
| 2785 double imm, | 2695 double imm, |
| 2786 const Register scratch) { | 2696 const Register scratch) { |
| 2787 DCHECK(VfpRegisterIsAvailable(dst)); | 2697 DCHECK(VfpRegisterIsAvailable(dst)); |
| 2788 DCHECK(!scratch.is(ip)); | 2698 DCHECK(!scratch.is(ip)); |
| 2789 uint32_t enc; | 2699 uint32_t enc; |
| 2790 // If the embedded constant pool is disabled, we can use the normal, inline | |
| 2791 // constant pool. If the embedded constant pool is enabled (via | |
| 2792 // FLAG_enable_embedded_constant_pool), we can only use it where the pool | |
| 2793 // pointer (pp) is valid. | |
| 2794 bool can_use_pool = | |
| 2795 !FLAG_enable_embedded_constant_pool || is_constant_pool_available(); | |
| 2796 if (CpuFeatures::IsSupported(VFPv3) && FitsVmovFPImmediate(imm, &enc)) { | 2700 if (CpuFeatures::IsSupported(VFPv3) && FitsVmovFPImmediate(imm, &enc)) { |
| 2797 CpuFeatureScope scope(this, VFPv3); | 2701 CpuFeatureScope scope(this, VFPv3); |
| 2798 // The double can be encoded in the instruction. | 2702 // The double can be encoded in the instruction. |
| 2799 // | 2703 // |
| 2800 // Dd = immediate | 2704 // Dd = immediate |
| 2801 // Instruction details available in ARM DDI 0406C.b, A8-936. | 2705 // Instruction details available in ARM DDI 0406C.b, A8-936. |
| 2802 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | imm4H(19-16) | | 2706 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | imm4H(19-16) | |
| 2803 // Vd(15-12) | 101(11-9) | sz=1(8) | imm4L(3-0) | 2707 // Vd(15-12) | 101(11-9) | sz=1(8) | imm4L(3-0) |
| 2804 int vd, d; | 2708 int vd, d; |
| 2805 dst.split_code(&vd, &d); | 2709 dst.split_code(&vd, &d); |
| 2806 emit(al | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | enc); | 2710 emit(al | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | enc); |
| 2807 } else if (CpuFeatures::IsSupported(ARMv7) && FLAG_enable_vldr_imm && | 2711 } else if (CpuFeatures::IsSupported(ARMv7) && FLAG_enable_vldr_imm) { |
| 2808 can_use_pool) { | |
| 2809 CpuFeatureScope scope(this, ARMv7); | 2712 CpuFeatureScope scope(this, ARMv7); |
| 2810 // TODO(jfb) Temporarily turned off until we have constant blinding or | 2713 // TODO(jfb) Temporarily turned off until we have constant blinding or |
| 2811 // some equivalent mitigation: an attacker can otherwise control | 2714 // some equivalent mitigation: an attacker can otherwise control |
| 2812 // generated data which also happens to be executable, a Very Bad | 2715 // generated data which also happens to be executable, a Very Bad |
| 2813 // Thing indeed. | 2716 // Thing indeed. |
| 2814 // Blinding gets tricky because we don't have xor, we probably | 2717 // Blinding gets tricky because we don't have xor, we probably |
| 2815 // need to add/subtract without losing precision, which requires a | 2718 // need to add/subtract without losing precision, which requires a |
| 2816 // cookie value that Lithium is probably better positioned to | 2719 // cookie value that Lithium is probably better positioned to |
| 2817 // choose. | 2720 // choose. |
| 2818 // We could also add a few peepholes here like detecting 0.0 and | 2721 // We could also add a few peepholes here like detecting 0.0 and |
| 2819 // -0.0 and doing a vmov from the sequestered d14, forcing denorms | 2722 // -0.0 and doing a vmov from the sequestered d14, forcing denorms |
| 2820 // to zero (we set flush-to-zero), and normalizing NaN values. | 2723 // to zero (we set flush-to-zero), and normalizing NaN values. |
| 2821 // We could also detect redundant values. | 2724 // We could also detect redundant values. |
| 2822 // The code could also randomize the order of values, though | 2725 // The code could also randomize the order of values, though |
| 2823 // that's tricky because vldr has a limited reach. Furthermore | 2726 // that's tricky because vldr has a limited reach. Furthermore |
| 2824 // it breaks load locality. | 2727 // it breaks load locality. |
| 2825 ConstantPoolEntry::Access access = ConstantPoolAddEntry(pc_offset(), imm); | 2728 ConstantPoolEntry::Access access = ConstantPoolAddEntry(pc_offset(), imm); |
| 2826 if (access == ConstantPoolEntry::OVERFLOWED) { | 2729 DCHECK(access == ConstantPoolEntry::REGULAR); |
| 2827 DCHECK(FLAG_enable_embedded_constant_pool); | 2730 USE(access); |
| 2828 // Emit instructions to load constant pool offset. | 2731 vldr(dst, MemOperand(pc, 0)); |
| 2829 movw(ip, 0); | |
| 2830 movt(ip, 0); | |
| 2831 // Load from constant pool at offset. | |
| 2832 vldr(dst, MemOperand(pp, ip)); | |
| 2833 } else { | |
| 2834 DCHECK(access == ConstantPoolEntry::REGULAR); | |
| 2835 vldr(dst, MemOperand(FLAG_enable_embedded_constant_pool ? pp : pc, 0)); | |
| 2836 } | |
| 2837 } else { | 2732 } else { |
| 2838 // Synthesise the double from ARM immediates. | 2733 // Synthesise the double from ARM immediates. |
| 2839 uint32_t lo, hi; | 2734 uint32_t lo, hi; |
| 2840 DoubleAsTwoUInt32(imm, &lo, &hi); | 2735 DoubleAsTwoUInt32(imm, &lo, &hi); |
| 2841 | 2736 |
| 2842 if (lo == hi) { | 2737 if (lo == hi) { |
| 2843 // Move the low and high parts of the double to a D register in one | 2738 // Move the low and high parts of the double to a D register in one |
| 2844 // instruction. | 2739 // instruction. |
| 2845 mov(ip, Operand(lo)); | 2740 mov(ip, Operand(lo)); |
| 2846 vmov(dst, ip, ip); | 2741 vmov(dst, ip, ip); |
| (...skipping 2192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5039 } | 4934 } |
| 5040 | 4935 |
| 5041 | 4936 |
| 5042 ConstantPoolEntry::Access Assembler::ConstantPoolAddEntry(int position, | 4937 ConstantPoolEntry::Access Assembler::ConstantPoolAddEntry(int position, |
| 5043 RelocInfo::Mode rmode, | 4938 RelocInfo::Mode rmode, |
| 5044 intptr_t value) { | 4939 intptr_t value) { |
| 5045 DCHECK(rmode != RelocInfo::COMMENT && rmode != RelocInfo::CONST_POOL && | 4940 DCHECK(rmode != RelocInfo::COMMENT && rmode != RelocInfo::CONST_POOL && |
| 5046 rmode != RelocInfo::NONE64); | 4941 rmode != RelocInfo::NONE64); |
| 5047 bool sharing_ok = RelocInfo::IsNone(rmode) || | 4942 bool sharing_ok = RelocInfo::IsNone(rmode) || |
| 5048 !(serializer_enabled() || rmode < RelocInfo::CELL); | 4943 !(serializer_enabled() || rmode < RelocInfo::CELL); |
| 5049 if (FLAG_enable_embedded_constant_pool) { | 4944 DCHECK(pending_32_bit_constants_.size() < kMaxNumPending32Constants); |
| 5050 return constant_pool_builder_.AddEntry(position, value, sharing_ok); | 4945 if (pending_32_bit_constants_.empty()) { |
| 5051 } else { | 4946 first_const_pool_32_use_ = position; |
| 5052 DCHECK(pending_32_bit_constants_.size() < kMaxNumPending32Constants); | 4947 } |
| 5053 if (pending_32_bit_constants_.empty()) { | 4948 ConstantPoolEntry entry(position, value, sharing_ok); |
| 5054 first_const_pool_32_use_ = position; | 4949 pending_32_bit_constants_.push_back(entry); |
| 5055 } | |
| 5056 ConstantPoolEntry entry(position, value, sharing_ok); | |
| 5057 pending_32_bit_constants_.push_back(entry); | |
| 5058 | 4950 |
| 5059 // Make sure the constant pool is not emitted in place of the next | 4951 // Make sure the constant pool is not emitted in place of the next |
| 5060 // instruction for which we just recorded relocation info. | 4952 // instruction for which we just recorded relocation info. |
| 5061 BlockConstPoolFor(1); | 4953 BlockConstPoolFor(1); |
| 5062 return ConstantPoolEntry::REGULAR; | 4954 return ConstantPoolEntry::REGULAR; |
| 5063 } | |
| 5064 } | 4955 } |
| 5065 | 4956 |
| 5066 | 4957 |
| 5067 ConstantPoolEntry::Access Assembler::ConstantPoolAddEntry(int position, | 4958 ConstantPoolEntry::Access Assembler::ConstantPoolAddEntry(int position, |
| 5068 double value) { | 4959 double value) { |
| 5069 if (FLAG_enable_embedded_constant_pool) { | 4960 DCHECK(pending_64_bit_constants_.size() < kMaxNumPending64Constants); |
| 5070 return constant_pool_builder_.AddEntry(position, value); | 4961 if (pending_64_bit_constants_.empty()) { |
| 5071 } else { | 4962 first_const_pool_64_use_ = position; |
| 5072 DCHECK(pending_64_bit_constants_.size() < kMaxNumPending64Constants); | 4963 } |
| 5073 if (pending_64_bit_constants_.empty()) { | 4964 ConstantPoolEntry entry(position, value); |
| 5074 first_const_pool_64_use_ = position; | 4965 pending_64_bit_constants_.push_back(entry); |
| 5075 } | |
| 5076 ConstantPoolEntry entry(position, value); | |
| 5077 pending_64_bit_constants_.push_back(entry); | |
| 5078 | 4966 |
| 5079 // Make sure the constant pool is not emitted in place of the next | 4967 // Make sure the constant pool is not emitted in place of the next |
| 5080 // instruction for which we just recorded relocation info. | 4968 // instruction for which we just recorded relocation info. |
| 5081 BlockConstPoolFor(1); | 4969 BlockConstPoolFor(1); |
| 5082 return ConstantPoolEntry::REGULAR; | 4970 return ConstantPoolEntry::REGULAR; |
| 5083 } | |
| 5084 } | 4971 } |
| 5085 | 4972 |
| 5086 | 4973 |
| 5087 void Assembler::BlockConstPoolFor(int instructions) { | 4974 void Assembler::BlockConstPoolFor(int instructions) { |
| 5088 if (FLAG_enable_embedded_constant_pool) { | |
| 5089 // Should be a no-op if using an embedded constant pool. | |
| 5090 DCHECK(pending_32_bit_constants_.empty()); | |
| 5091 DCHECK(pending_64_bit_constants_.empty()); | |
| 5092 return; | |
| 5093 } | |
| 5094 | |
| 5095 int pc_limit = pc_offset() + instructions * kInstrSize; | 4975 int pc_limit = pc_offset() + instructions * kInstrSize; |
| 5096 if (no_const_pool_before_ < pc_limit) { | 4976 if (no_const_pool_before_ < pc_limit) { |
| 5097 // Max pool start (if we need a jump and an alignment). | 4977 // Max pool start (if we need a jump and an alignment). |
| 5098 #ifdef DEBUG | 4978 #ifdef DEBUG |
| 5099 int start = pc_limit + kInstrSize + 2 * kPointerSize; | 4979 int start = pc_limit + kInstrSize + 2 * kPointerSize; |
| 5100 DCHECK(pending_32_bit_constants_.empty() || | 4980 DCHECK(pending_32_bit_constants_.empty() || |
| 5101 (start - first_const_pool_32_use_ + | 4981 (start - first_const_pool_32_use_ + |
| 5102 pending_64_bit_constants_.size() * kDoubleSize < | 4982 pending_64_bit_constants_.size() * kDoubleSize < |
| 5103 kMaxDistToIntPool)); | 4983 kMaxDistToIntPool)); |
| 5104 DCHECK(pending_64_bit_constants_.empty() || | 4984 DCHECK(pending_64_bit_constants_.empty() || |
| 5105 (start - first_const_pool_64_use_ < kMaxDistToFPPool)); | 4985 (start - first_const_pool_64_use_ < kMaxDistToFPPool)); |
| 5106 #endif | 4986 #endif |
| 5107 no_const_pool_before_ = pc_limit; | 4987 no_const_pool_before_ = pc_limit; |
| 5108 } | 4988 } |
| 5109 | 4989 |
| 5110 if (next_buffer_check_ < no_const_pool_before_) { | 4990 if (next_buffer_check_ < no_const_pool_before_) { |
| 5111 next_buffer_check_ = no_const_pool_before_; | 4991 next_buffer_check_ = no_const_pool_before_; |
| 5112 } | 4992 } |
| 5113 } | 4993 } |
| 5114 | 4994 |
| 5115 | 4995 |
| 5116 void Assembler::CheckConstPool(bool force_emit, bool require_jump) { | 4996 void Assembler::CheckConstPool(bool force_emit, bool require_jump) { |
| 5117 if (FLAG_enable_embedded_constant_pool) { | |
| 5118 // Should be a no-op if using an embedded constant pool. | |
| 5119 DCHECK(pending_32_bit_constants_.empty()); | |
| 5120 DCHECK(pending_64_bit_constants_.empty()); | |
| 5121 return; | |
| 5122 } | |
| 5123 | |
| 5124 // Some short sequence of instruction mustn't be broken up by constant pool | 4997 // Some short sequence of instruction mustn't be broken up by constant pool |
| 5125 // emission, such sequences are protected by calls to BlockConstPoolFor and | 4998 // emission, such sequences are protected by calls to BlockConstPoolFor and |
| 5126 // BlockConstPoolScope. | 4999 // BlockConstPoolScope. |
| 5127 if (is_const_pool_blocked()) { | 5000 if (is_const_pool_blocked()) { |
| 5128 // Something is wrong if emission is forced and blocked at the same time. | 5001 // Something is wrong if emission is forced and blocked at the same time. |
| 5129 DCHECK(!force_emit); | 5002 DCHECK(!force_emit); |
| 5130 return; | 5003 return; |
| 5131 } | 5004 } |
| 5132 | 5005 |
| 5133 // There is nothing to do if there are no pending constant pool entries. | 5006 // There is nothing to do if there are no pending constant pool entries. |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5326 if (after_pool.is_linked()) { | 5199 if (after_pool.is_linked()) { |
| 5327 bind(&after_pool); | 5200 bind(&after_pool); |
| 5328 } | 5201 } |
| 5329 } | 5202 } |
| 5330 | 5203 |
| 5331 // Since a constant pool was just emitted, move the check offset forward by | 5204 // Since a constant pool was just emitted, move the check offset forward by |
| 5332 // the standard interval. | 5205 // the standard interval. |
| 5333 next_buffer_check_ = pc_offset() + kCheckPoolInterval; | 5206 next_buffer_check_ = pc_offset() + kCheckPoolInterval; |
| 5334 } | 5207 } |
| 5335 | 5208 |
| 5336 | |
| 5337 void Assembler::PatchConstantPoolAccessInstruction( | |
| 5338 int pc_offset, int offset, ConstantPoolEntry::Access access, | |
| 5339 ConstantPoolEntry::Type type) { | |
| 5340 DCHECK(FLAG_enable_embedded_constant_pool); | |
| 5341 Address pc = buffer_ + pc_offset; | |
| 5342 | |
| 5343 // Patch vldr/ldr instruction with correct offset. | |
| 5344 Instr instr = instr_at(pc); | |
| 5345 if (access == ConstantPoolEntry::OVERFLOWED) { | |
| 5346 if (CpuFeatures::IsSupported(ARMv7)) { | |
| 5347 CpuFeatureScope scope(this, ARMv7); | |
| 5348 // Instructions to patch must be 'movw rd, [#0]' and 'movt rd, [#0]. | |
| 5349 Instr next_instr = instr_at(pc + kInstrSize); | |
| 5350 DCHECK((IsMovW(instr) && Instruction::ImmedMovwMovtValue(instr) == 0)); | |
| 5351 DCHECK((IsMovT(next_instr) && | |
| 5352 Instruction::ImmedMovwMovtValue(next_instr) == 0)); | |
| 5353 instr_at_put(pc, PatchMovwImmediate(instr, offset & 0xffff)); | |
| 5354 instr_at_put(pc + kInstrSize, | |
| 5355 PatchMovwImmediate(next_instr, offset >> 16)); | |
| 5356 } else { | |
| 5357 // Instructions to patch must be 'mov rd, [#0]' and 'orr rd, rd, [#0]. | |
| 5358 Instr instr_2 = instr_at(pc + kInstrSize); | |
| 5359 Instr instr_3 = instr_at(pc + 2 * kInstrSize); | |
| 5360 Instr instr_4 = instr_at(pc + 3 * kInstrSize); | |
| 5361 DCHECK((IsMovImmed(instr) && Instruction::Immed8Value(instr) == 0)); | |
| 5362 DCHECK((IsOrrImmed(instr_2) && Instruction::Immed8Value(instr_2) == 0) && | |
| 5363 GetRn(instr_2).is(GetRd(instr_2))); | |
| 5364 DCHECK((IsOrrImmed(instr_3) && Instruction::Immed8Value(instr_3) == 0) && | |
| 5365 GetRn(instr_3).is(GetRd(instr_3))); | |
| 5366 DCHECK((IsOrrImmed(instr_4) && Instruction::Immed8Value(instr_4) == 0) && | |
| 5367 GetRn(instr_4).is(GetRd(instr_4))); | |
| 5368 instr_at_put(pc, PatchShiftImm(instr, (offset & kImm8Mask))); | |
| 5369 instr_at_put(pc + kInstrSize, | |
| 5370 PatchShiftImm(instr_2, (offset & (kImm8Mask << 8)))); | |
| 5371 instr_at_put(pc + 2 * kInstrSize, | |
| 5372 PatchShiftImm(instr_3, (offset & (kImm8Mask << 16)))); | |
| 5373 instr_at_put(pc + 3 * kInstrSize, | |
| 5374 PatchShiftImm(instr_4, (offset & (kImm8Mask << 24)))); | |
| 5375 } | |
| 5376 } else if (type == ConstantPoolEntry::DOUBLE) { | |
| 5377 // Instruction to patch must be 'vldr rd, [pp, #0]'. | |
| 5378 DCHECK((IsVldrDPpImmediateOffset(instr) && | |
| 5379 GetVldrDRegisterImmediateOffset(instr) == 0)); | |
| 5380 DCHECK(is_uint10(offset)); | |
| 5381 instr_at_put(pc, SetVldrDRegisterImmediateOffset(instr, offset)); | |
| 5382 } else { | |
| 5383 // Instruction to patch must be 'ldr rd, [pp, #0]'. | |
| 5384 DCHECK((IsLdrPpImmediateOffset(instr) && | |
| 5385 GetLdrRegisterImmediateOffset(instr) == 0)); | |
| 5386 DCHECK(is_uint12(offset)); | |
| 5387 instr_at_put(pc, SetLdrRegisterImmediateOffset(instr, offset)); | |
| 5388 } | |
| 5389 } | |
| 5390 | |
| 5391 PatchingAssembler::PatchingAssembler(IsolateData isolate_data, byte* address, | 5209 PatchingAssembler::PatchingAssembler(IsolateData isolate_data, byte* address, |
| 5392 int instructions) | 5210 int instructions) |
| 5393 : Assembler(isolate_data, address, instructions * kInstrSize + kGap) { | 5211 : Assembler(isolate_data, address, instructions * kInstrSize + kGap) { |
| 5394 DCHECK_EQ(reloc_info_writer.pos(), buffer_ + buffer_size_); | 5212 DCHECK_EQ(reloc_info_writer.pos(), buffer_ + buffer_size_); |
| 5395 } | 5213 } |
| 5396 | 5214 |
| 5397 PatchingAssembler::~PatchingAssembler() { | 5215 PatchingAssembler::~PatchingAssembler() { |
| 5398 // Check that we don't have any pending constant pools. | 5216 // Check that we don't have any pending constant pools. |
| 5399 DCHECK(pending_32_bit_constants_.empty()); | 5217 DCHECK(pending_32_bit_constants_.empty()); |
| 5400 DCHECK(pending_64_bit_constants_.empty()); | 5218 DCHECK(pending_64_bit_constants_.empty()); |
| 5401 | 5219 |
| 5402 // Check that the code was patched as expected. | 5220 // Check that the code was patched as expected. |
| 5403 DCHECK_EQ(pc_, buffer_ + buffer_size_ - kGap); | 5221 DCHECK_EQ(pc_, buffer_ + buffer_size_ - kGap); |
| 5404 DCHECK_EQ(reloc_info_writer.pos(), buffer_ + buffer_size_); | 5222 DCHECK_EQ(reloc_info_writer.pos(), buffer_ + buffer_size_); |
| 5405 } | 5223 } |
| 5406 | 5224 |
| 5407 void PatchingAssembler::Emit(Address addr) { | 5225 void PatchingAssembler::Emit(Address addr) { |
| 5408 emit(reinterpret_cast<Instr>(addr)); | 5226 emit(reinterpret_cast<Instr>(addr)); |
| 5409 } | 5227 } |
| 5410 | 5228 |
| 5411 void PatchingAssembler::FlushICache(Isolate* isolate) { | 5229 void PatchingAssembler::FlushICache(Isolate* isolate) { |
| 5412 Assembler::FlushICache(isolate, buffer_, buffer_size_ - kGap); | 5230 Assembler::FlushICache(isolate, buffer_, buffer_size_ - kGap); |
| 5413 } | 5231 } |
| 5414 | 5232 |
| 5415 } // namespace internal | 5233 } // namespace internal |
| 5416 } // namespace v8 | 5234 } // namespace v8 |
| 5417 | 5235 |
| 5418 #endif // V8_TARGET_ARCH_ARM | 5236 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |