Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(704)

Side by Side Diff: src/arm/assembler-arm.cc

Issue 1155703006: Revert of Embedded constant pools. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/arm/assembler-arm.h ('k') | src/arm/assembler-arm-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 // ----------------------------------------------------------------------------- 227 // -----------------------------------------------------------------------------
228 // Implementation of RelocInfo 228 // Implementation of RelocInfo
229 229
230 // static 230 // static
231 const int RelocInfo::kApplyMask = 0; 231 const int RelocInfo::kApplyMask = 0;
232 232
233 233
234 bool RelocInfo::IsCodedSpecially() { 234 bool RelocInfo::IsCodedSpecially() {
235 // The deserializer needs to know whether a pointer is specially coded.  Being 235 // The deserializer needs to know whether a pointer is specially coded.  Being
236 // specially coded on ARM means that it is a movw/movt instruction, or is an 236 // specially coded on ARM means that it is a movw/movt instruction, or is an
237 // embedded constant pool entry.  These only occur if 237 // out of line constant pool entry.  These only occur if
238 // FLAG_enable_embedded_constant_pool is true. 238 // FLAG_enable_ool_constant_pool is true.
239 return FLAG_enable_embedded_constant_pool; 239 return FLAG_enable_ool_constant_pool;
240 } 240 }
241 241
242 242
243 bool RelocInfo::IsInConstantPool() { 243 bool RelocInfo::IsInConstantPool() {
244 return Assembler::is_constant_pool_load(pc_); 244 return Assembler::is_constant_pool_load(pc_);
245 } 245 }
246 246
247 247
248 // ----------------------------------------------------------------------------- 248 // -----------------------------------------------------------------------------
249 // Implementation of Operand and MemOperand 249 // Implementation of Operand and MemOperand
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 const Instr kLdrRegFpNegOffsetPattern = 442 const Instr kLdrRegFpNegOffsetPattern =
443 al | B26 | L | NegOffset | kRegister_fp_Code * B16; 443 al | B26 | L | NegOffset | kRegister_fp_Code * B16;
444 const Instr kStrRegFpNegOffsetPattern = 444 const Instr kStrRegFpNegOffsetPattern =
445 al | B26 | NegOffset | kRegister_fp_Code * B16; 445 al | B26 | NegOffset | kRegister_fp_Code * B16;
446 const Instr kLdrStrInstrTypeMask = 0xffff0000; 446 const Instr kLdrStrInstrTypeMask = 0xffff0000;
447 447
448 448
449 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size) 449 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
450 : AssemblerBase(isolate, buffer, buffer_size), 450 : AssemblerBase(isolate, buffer, buffer_size),
451 recorded_ast_id_(TypeFeedbackId::None()), 451 recorded_ast_id_(TypeFeedbackId::None()),
452 constant_pool_builder_(kLdrMaxReachBits, kVldrMaxReachBits), 452 constant_pool_builder_(),
453 positions_recorder_(this) { 453 positions_recorder_(this) {
454 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_); 454 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
455 num_pending_32_bit_constants_ = 0; 455 num_pending_32_bit_reloc_info_ = 0;
456 num_pending_64_bit_constants_ = 0; 456 num_pending_64_bit_reloc_info_ = 0;
457 next_buffer_check_ = 0; 457 next_buffer_check_ = 0;
458 const_pool_blocked_nesting_ = 0; 458 const_pool_blocked_nesting_ = 0;
459 no_const_pool_before_ = 0; 459 no_const_pool_before_ = 0;
460 first_const_pool_32_use_ = -1; 460 first_const_pool_32_use_ = -1;
461 first_const_pool_64_use_ = -1; 461 first_const_pool_64_use_ = -1;
462 last_bound_pos_ = 0; 462 last_bound_pos_ = 0;
463 ClearRecordedAstId(); 463 ClearRecordedAstId();
464 } 464 }
465 465
466 466
467 Assembler::~Assembler() { 467 Assembler::~Assembler() {
468 DCHECK(const_pool_blocked_nesting_ == 0); 468 DCHECK(const_pool_blocked_nesting_ == 0);
469 } 469 }
470 470
471 471
472 void Assembler::GetCode(CodeDesc* desc) { 472 void Assembler::GetCode(CodeDesc* desc) {
473 reloc_info_writer.Finish(); 473 reloc_info_writer.Finish();
474 474 if (!FLAG_enable_ool_constant_pool) {
475 // Emit constant pool if necessary. 475 // Emit constant pool if necessary.
476 int constant_pool_offset = 0;
477 if (FLAG_enable_embedded_constant_pool) {
478 constant_pool_offset = EmitEmbeddedConstantPool();
479 } else {
480 CheckConstPool(true, false); 476 CheckConstPool(true, false);
481 DCHECK(num_pending_32_bit_constants_ == 0); 477 DCHECK(num_pending_32_bit_reloc_info_ == 0);
482 DCHECK(num_pending_64_bit_constants_ == 0); 478 DCHECK(num_pending_64_bit_reloc_info_ == 0);
483 } 479 }
484 // Set up code descriptor. 480 // Set up code descriptor.
485 desc->buffer = buffer_; 481 desc->buffer = buffer_;
486 desc->buffer_size = buffer_size_; 482 desc->buffer_size = buffer_size_;
487 desc->instr_size = pc_offset(); 483 desc->instr_size = pc_offset();
488 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); 484 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
489 desc->constant_pool_size =
490 (constant_pool_offset ? desc->instr_size - constant_pool_offset : 0);
491 desc->origin = this; 485 desc->origin = this;
492 } 486 }
493 487
494 488
495 void Assembler::Align(int m) { 489 void Assembler::Align(int m) {
496 DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m)); 490 DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m));
497 while ((pc_offset() & (m - 1)) != 0) { 491 while ((pc_offset() & (m - 1)) != 0) {
498 nop(); 492 nop();
499 } 493 }
500 } 494 }
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 616
623 617
624 Register Assembler::GetRm(Instr instr) { 618 Register Assembler::GetRm(Instr instr) {
625 Register reg; 619 Register reg;
626 reg.code_ = Instruction::RmValue(instr); 620 reg.code_ = Instruction::RmValue(instr);
627 return reg; 621 return reg;
628 } 622 }
629 623
630 624
631 Instr Assembler::GetConsantPoolLoadPattern() { 625 Instr Assembler::GetConsantPoolLoadPattern() {
632 if (FLAG_enable_embedded_constant_pool) { 626 if (FLAG_enable_ool_constant_pool) {
633 return kLdrPpImmedPattern; 627 return kLdrPpImmedPattern;
634 } else { 628 } else {
635 return kLdrPCImmedPattern; 629 return kLdrPCImmedPattern;
636 } 630 }
637 } 631 }
638 632
639 633
640 Instr Assembler::GetConsantPoolLoadMask() { 634 Instr Assembler::GetConsantPoolLoadMask() {
641 if (FLAG_enable_embedded_constant_pool) { 635 if (FLAG_enable_ool_constant_pool) {
642 return kLdrPpImmedMask; 636 return kLdrPpImmedMask;
643 } else { 637 } else {
644 return kLdrPCImmedMask; 638 return kLdrPCImmedMask;
645 } 639 }
646 } 640 }
647 641
648 642
649 bool Assembler::IsPush(Instr instr) { 643 bool Assembler::IsPush(Instr instr) {
650 return ((instr & ~kRdMask) == kPushRegPattern); 644 return ((instr & ~kRdMask) == kPushRegPattern);
651 } 645 }
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
1043 return assembler->serializer_enabled(); 1037 return assembler->serializer_enabled();
1044 } else if (RelocInfo::IsNone(rmode_)) { 1038 } else if (RelocInfo::IsNone(rmode_)) {
1045 return false; 1039 return false;
1046 } 1040 }
1047 return true; 1041 return true;
1048 } 1042 }
1049 1043
1050 1044
1051 static bool use_mov_immediate_load(const Operand& x, 1045 static bool use_mov_immediate_load(const Operand& x,
1052 const Assembler* assembler) { 1046 const Assembler* assembler) {
1053 if (FLAG_enable_embedded_constant_pool && assembler != NULL && 1047 if (FLAG_enable_ool_constant_pool && assembler != NULL &&
1054 !assembler->is_constant_pool_available()) { 1048 !assembler->is_ool_constant_pool_available()) {
1055 return true; 1049 return true;
1056 } else if (CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) && 1050 } else if (CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) &&
1057 (assembler == NULL || !assembler->predictable_code_size())) { 1051 (assembler == NULL || !assembler->predictable_code_size())) {
1058 // Prefer movw / movt to constant pool if it is more efficient on the CPU. 1052 // Prefer movw / movt to constant pool if it is more efficient on the CPU.
1059 return true; 1053 return true;
1060 } else if (x.must_output_reloc_info(assembler)) { 1054 } else if (x.must_output_reloc_info(assembler)) {
1061 // Prefer constant pool if data is likely to be patched. 1055 // Prefer constant pool if data is likely to be patched.
1062 return false; 1056 return false;
1063 } else { 1057 } else {
1064 // Otherwise, use immediate load if movw / movt is available. 1058 // Otherwise, use immediate load if movw / movt is available.
1065 return CpuFeatures::IsSupported(ARMv7); 1059 return CpuFeatures::IsSupported(ARMv7);
1066 } 1060 }
1067 } 1061 }
1068 1062
1069 1063
1070 int Operand::instructions_required(const Assembler* assembler, 1064 int Operand::instructions_required(const Assembler* assembler,
1071 Instr instr) const { 1065 Instr instr) const {
1072 if (rm_.is_valid()) return 1; 1066 if (rm_.is_valid()) return 1;
1073 uint32_t dummy1, dummy2; 1067 uint32_t dummy1, dummy2;
1074 if (must_output_reloc_info(assembler) || 1068 if (must_output_reloc_info(assembler) ||
1075 !fits_shifter(imm32_, &dummy1, &dummy2, &instr)) { 1069 !fits_shifter(imm32_, &dummy1, &dummy2, &instr)) {
1076 // The immediate operand cannot be encoded as a shifter operand, or use of 1070 // The immediate operand cannot be encoded as a shifter operand, or use of
1077 // constant pool is required. First account for the instructions required 1071 // constant pool is required. First account for the instructions required
1078 // for the constant pool or immediate load 1072 // for the constant pool or immediate load
1079 int instructions; 1073 int instructions;
1080 if (use_mov_immediate_load(*this, assembler)) { 1074 if (use_mov_immediate_load(*this, assembler)) {
1081 // A movw / movt or mov / orr immediate load. 1075 // A movw / movt or mov / orr immediate load.
1082 instructions = CpuFeatures::IsSupported(ARMv7) ? 2 : 4; 1076 instructions = CpuFeatures::IsSupported(ARMv7) ? 2 : 4;
1083 } else if (assembler != NULL && 1077 } else if (assembler != NULL && assembler->use_extended_constant_pool()) {
1084 assembler->ConstantPoolAccessIsInOverflow()) { 1078 // An extended constant pool load.
1085 // An overflowed constant pool load.
1086 instructions = CpuFeatures::IsSupported(ARMv7) ? 3 : 5; 1079 instructions = CpuFeatures::IsSupported(ARMv7) ? 3 : 5;
1087 } else { 1080 } else {
1088 // A small constant pool load. 1081 // A small constant pool load.
1089 instructions = 1; 1082 instructions = 1;
1090 } 1083 }
1091 1084
1092 if ((instr & ~kCondMask) != 13 * B21) { // mov, S not set 1085 if ((instr & ~kCondMask) != 13 * B21) { // mov, S not set
1093 // For a mov or mvn instruction which doesn't set the condition 1086 // For a mov or mvn instruction which doesn't set the condition
1094 // code, the constant pool or immediate load is enough, otherwise we need 1087 // code, the constant pool or immediate load is enough, otherwise we need
1095 // to account for the actual instruction being requested. 1088 // to account for the actual instruction being requested.
1096 instructions += 1; 1089 instructions += 1;
1097 } 1090 }
1098 return instructions; 1091 return instructions;
1099 } else { 1092 } else {
1100 // No use of constant pool and the immediate operand can be encoded as a 1093 // No use of constant pool and the immediate operand can be encoded as a
1101 // shifter operand. 1094 // shifter operand.
1102 return 1; 1095 return 1;
1103 } 1096 }
1104 } 1097 }
1105 1098
1106 1099
1107 void Assembler::move_32_bit_immediate(Register rd, 1100 void Assembler::move_32_bit_immediate(Register rd,
1108 const Operand& x, 1101 const Operand& x,
1109 Condition cond) { 1102 Condition cond) {
1103 RelocInfo rinfo(pc_, x.rmode_, x.imm32_, NULL);
1110 uint32_t imm32 = static_cast<uint32_t>(x.imm32_); 1104 uint32_t imm32 = static_cast<uint32_t>(x.imm32_);
1111 if (x.must_output_reloc_info(this)) { 1105 if (x.must_output_reloc_info(this)) {
1112 RecordRelocInfo(x.rmode_); 1106 RecordRelocInfo(rinfo);
1113 } 1107 }
1114 1108
1115 if (use_mov_immediate_load(x, this)) { 1109 if (use_mov_immediate_load(x, this)) {
1116 Register target = rd.code() == pc.code() ? ip : rd; 1110 Register target = rd.code() == pc.code() ? ip : rd;
1117 if (CpuFeatures::IsSupported(ARMv7)) { 1111 if (CpuFeatures::IsSupported(ARMv7)) {
1118 if (!FLAG_enable_embedded_constant_pool && 1112 if (!FLAG_enable_ool_constant_pool && x.must_output_reloc_info(this)) {
1119 x.must_output_reloc_info(this)) {
1120 // Make sure the movw/movt doesn't get separated. 1113 // Make sure the movw/movt doesn't get separated.
1121 BlockConstPoolFor(2); 1114 BlockConstPoolFor(2);
1122 } 1115 }
1123 movw(target, imm32 & 0xffff, cond); 1116 movw(target, imm32 & 0xffff, cond);
1124 movt(target, imm32 >> 16, cond); 1117 movt(target, imm32 >> 16, cond);
1125 } else { 1118 } else {
1126 DCHECK(FLAG_enable_embedded_constant_pool); 1119 DCHECK(FLAG_enable_ool_constant_pool);
1127 mov(target, Operand(imm32 & kImm8Mask), LeaveCC, cond); 1120 mov(target, Operand(imm32 & kImm8Mask), LeaveCC, cond);
1128 orr(target, target, Operand(imm32 & (kImm8Mask << 8)), LeaveCC, cond); 1121 orr(target, target, Operand(imm32 & (kImm8Mask << 8)), LeaveCC, cond);
1129 orr(target, target, Operand(imm32 & (kImm8Mask << 16)), LeaveCC, cond); 1122 orr(target, target, Operand(imm32 & (kImm8Mask << 16)), LeaveCC, cond);
1130 orr(target, target, Operand(imm32 & (kImm8Mask << 24)), LeaveCC, cond); 1123 orr(target, target, Operand(imm32 & (kImm8Mask << 24)), LeaveCC, cond);
1131 } 1124 }
1132 if (target.code() != rd.code()) { 1125 if (target.code() != rd.code()) {
1133 mov(rd, target, LeaveCC, cond); 1126 mov(rd, target, LeaveCC, cond);
1134 } 1127 }
1135 } else { 1128 } else {
1136 DCHECK(!FLAG_enable_embedded_constant_pool || is_constant_pool_available()); 1129 DCHECK(!FLAG_enable_ool_constant_pool || is_ool_constant_pool_available());
1137 ConstantPoolEntry::Access access = 1130 ConstantPoolArray::LayoutSection section = ConstantPoolAddEntry(rinfo);
1138 ConstantPoolAddEntry(pc_offset(), x.rmode_, x.imm32_); 1131 if (section == ConstantPoolArray::EXTENDED_SECTION) {
1139 if (access == ConstantPoolEntry::OVERFLOWED) { 1132 DCHECK(FLAG_enable_ool_constant_pool);
1140 DCHECK(FLAG_enable_embedded_constant_pool);
1141 Register target = rd.code() == pc.code() ? ip : rd; 1133 Register target = rd.code() == pc.code() ? ip : rd;
1142 // Emit instructions to load constant pool offset. 1134 // Emit instructions to load constant pool offset.
1143 if (CpuFeatures::IsSupported(ARMv7)) { 1135 if (CpuFeatures::IsSupported(ARMv7)) {
1144 movw(target, 0, cond); 1136 movw(target, 0, cond);
1145 movt(target, 0, cond); 1137 movt(target, 0, cond);
1146 } else { 1138 } else {
1147 mov(target, Operand(0), LeaveCC, cond); 1139 mov(target, Operand(0), LeaveCC, cond);
1148 orr(target, target, Operand(0), LeaveCC, cond); 1140 orr(target, target, Operand(0), LeaveCC, cond);
1149 orr(target, target, Operand(0), LeaveCC, cond); 1141 orr(target, target, Operand(0), LeaveCC, cond);
1150 orr(target, target, Operand(0), LeaveCC, cond); 1142 orr(target, target, Operand(0), LeaveCC, cond);
1151 } 1143 }
1152 // Load from constant pool at offset. 1144 // Load from constant pool at offset.
1153 ldr(rd, MemOperand(pp, target), cond); 1145 ldr(rd, MemOperand(pp, target), cond);
1154 } else { 1146 } else {
1155 DCHECK(access == ConstantPoolEntry::REGULAR); 1147 DCHECK(section == ConstantPoolArray::SMALL_SECTION);
1156 ldr(rd, MemOperand(FLAG_enable_embedded_constant_pool ? pp : pc, 0), 1148 ldr(rd, MemOperand(FLAG_enable_ool_constant_pool ? pp : pc, 0), cond);
1157 cond);
1158 } 1149 }
1159 } 1150 }
1160 } 1151 }
1161 1152
1162 1153
1163 void Assembler::addrmod1(Instr instr, 1154 void Assembler::addrmod1(Instr instr,
1164 Register rn, 1155 Register rn,
1165 Register rd, 1156 Register rd,
1166 const Operand& x) { 1157 const Operand& x) {
1167 CheckBuffer(); 1158 CheckBuffer();
(...skipping 1388 matching lines...) Expand 10 before | Expand all | Expand 10 after
2556 if (CpuFeatures::IsSupported(VFP3) && FitsVMOVDoubleImmediate(imm, &enc)) { 2547 if (CpuFeatures::IsSupported(VFP3) && FitsVMOVDoubleImmediate(imm, &enc)) {
2557 // The double can be encoded in the instruction. 2548 // The double can be encoded in the instruction.
2558 // 2549 //
2559 // Dd = immediate 2550 // Dd = immediate
2560 // Instruction details available in ARM DDI 0406C.b, A8-936. 2551 // Instruction details available in ARM DDI 0406C.b, A8-936.
2561 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | imm4H(19-16) | 2552 // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | imm4H(19-16) |
2562 // Vd(15-12) | 101(11-9) | sz=1(8) | imm4L(3-0) 2553 // Vd(15-12) | 101(11-9) | sz=1(8) | imm4L(3-0)
2563 int vd, d; 2554 int vd, d;
2564 dst.split_code(&vd, &d); 2555 dst.split_code(&vd, &d);
2565 emit(al | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | enc); 2556 emit(al | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | enc);
2566 } else if (FLAG_enable_vldr_imm && is_constant_pool_available()) { 2557 } else if (FLAG_enable_vldr_imm && is_ool_constant_pool_available()) {
2567 // TODO(jfb) Temporarily turned off until we have constant blinding or 2558 // TODO(jfb) Temporarily turned off until we have constant blinding or
2568 // some equivalent mitigation: an attacker can otherwise control 2559 // some equivalent mitigation: an attacker can otherwise control
2569 // generated data which also happens to be executable, a Very Bad 2560 // generated data which also happens to be executable, a Very Bad
2570 // Thing indeed. 2561 // Thing indeed.
2571 // Blinding gets tricky because we don't have xor, we probably 2562 // Blinding gets tricky because we don't have xor, we probably
2572 // need to add/subtract without losing precision, which requires a 2563 // need to add/subtract without losing precision, which requires a
2573 // cookie value that Lithium is probably better positioned to 2564 // cookie value that Lithium is probably better positioned to
2574 // choose. 2565 // choose.
2575 // We could also add a few peepholes here like detecting 0.0 and 2566 // We could also add a few peepholes here like detecting 0.0 and
2576 // -0.0 and doing a vmov from the sequestered d14, forcing denorms 2567 // -0.0 and doing a vmov from the sequestered d14, forcing denorms
2577 // to zero (we set flush-to-zero), and normalizing NaN values. 2568 // to zero (we set flush-to-zero), and normalizing NaN values.
2578 // We could also detect redundant values. 2569 // We could also detect redundant values.
2579 // The code could also randomize the order of values, though 2570 // The code could also randomize the order of values, though
2580 // that's tricky because vldr has a limited reach. Furthermore 2571 // that's tricky because vldr has a limited reach. Furthermore
2581 // it breaks load locality. 2572 // it breaks load locality.
2582 ConstantPoolEntry::Access access = ConstantPoolAddEntry(pc_offset(), imm); 2573 RelocInfo rinfo(pc_, imm);
2583 if (access == ConstantPoolEntry::OVERFLOWED) { 2574 ConstantPoolArray::LayoutSection section = ConstantPoolAddEntry(rinfo);
2584 DCHECK(FLAG_enable_embedded_constant_pool); 2575 if (section == ConstantPoolArray::EXTENDED_SECTION) {
2576 DCHECK(FLAG_enable_ool_constant_pool);
2585 // Emit instructions to load constant pool offset. 2577 // Emit instructions to load constant pool offset.
2586 movw(ip, 0); 2578 movw(ip, 0);
2587 movt(ip, 0); 2579 movt(ip, 0);
2588 // Load from constant pool at offset. 2580 // Load from constant pool at offset.
2589 vldr(dst, MemOperand(pp, ip)); 2581 vldr(dst, MemOperand(pp, ip));
2590 } else { 2582 } else {
2591 DCHECK(access == ConstantPoolEntry::REGULAR); 2583 DCHECK(section == ConstantPoolArray::SMALL_SECTION);
2592 vldr(dst, MemOperand(FLAG_enable_embedded_constant_pool ? pp : pc, 0)); 2584 vldr(dst, MemOperand(FLAG_enable_ool_constant_pool ? pp : pc, 0));
2593 } 2585 }
2594 } else { 2586 } else {
2595 // Synthesise the double from ARM immediates. 2587 // Synthesise the double from ARM immediates.
2596 uint32_t lo, hi; 2588 uint32_t lo, hi;
2597 DoubleAsTwoUInt32(imm, &lo, &hi); 2589 DoubleAsTwoUInt32(imm, &lo, &hi);
2598 2590
2599 if (lo == hi) { 2591 if (lo == hi) {
2600 // Move the low and high parts of the double to a D register in one 2592 // Move the low and high parts of the double to a D register in one
2601 // instruction. 2593 // instruction.
2602 mov(ip, Operand(lo)); 2594 mov(ip, Operand(lo));
(...skipping 954 matching lines...) Expand 10 before | Expand all | Expand 10 after
3557 DeleteArray(buffer_); 3549 DeleteArray(buffer_);
3558 buffer_ = desc.buffer; 3550 buffer_ = desc.buffer;
3559 buffer_size_ = desc.buffer_size; 3551 buffer_size_ = desc.buffer_size;
3560 pc_ += pc_delta; 3552 pc_ += pc_delta;
3561 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, 3553 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
3562 reloc_info_writer.last_pc() + pc_delta); 3554 reloc_info_writer.last_pc() + pc_delta);
3563 3555
3564 // None of our relocation types are pc relative pointing outside the code 3556 // None of our relocation types are pc relative pointing outside the code
3565 // buffer nor pc absolute pointing inside the code buffer, so there is no need 3557 // buffer nor pc absolute pointing inside the code buffer, so there is no need
3566 // to relocate any emitted relocation entries. 3558 // to relocate any emitted relocation entries.
3559
3560 // Relocate pending relocation entries.
3561 for (int i = 0; i < num_pending_32_bit_reloc_info_; i++) {
3562 RelocInfo& rinfo = pending_32_bit_reloc_info_[i];
3563 DCHECK(rinfo.rmode() != RelocInfo::COMMENT &&
3564 rinfo.rmode() != RelocInfo::POSITION);
3565 if (rinfo.rmode() != RelocInfo::JS_RETURN) {
3566 rinfo.set_pc(rinfo.pc() + pc_delta);
3567 }
3568 }
3569 for (int i = 0; i < num_pending_64_bit_reloc_info_; i++) {
3570 RelocInfo& rinfo = pending_64_bit_reloc_info_[i];
3571 DCHECK(rinfo.rmode() == RelocInfo::NONE64);
3572 rinfo.set_pc(rinfo.pc() + pc_delta);
3573 }
3574 constant_pool_builder_.Relocate(pc_delta);
3567 } 3575 }
3568 3576
3569 3577
3570 void Assembler::db(uint8_t data) { 3578 void Assembler::db(uint8_t data) {
3571 // No relocation info should be pending while using db. db is used 3579 // No relocation info should be pending while using db. db is used
3572 // to write pure data with no pointers and the constant pool should 3580 // to write pure data with no pointers and the constant pool should
3573 // be emitted before using db. 3581 // be emitted before using db.
3574 DCHECK(num_pending_32_bit_constants_ == 0); 3582 DCHECK(num_pending_32_bit_reloc_info_ == 0);
3575 DCHECK(num_pending_64_bit_constants_ == 0); 3583 DCHECK(num_pending_64_bit_reloc_info_ == 0);
3576 CheckBuffer(); 3584 CheckBuffer();
3577 *reinterpret_cast<uint8_t*>(pc_) = data; 3585 *reinterpret_cast<uint8_t*>(pc_) = data;
3578 pc_ += sizeof(uint8_t); 3586 pc_ += sizeof(uint8_t);
3579 } 3587 }
3580 3588
3581 3589
3582 void Assembler::dd(uint32_t data) { 3590 void Assembler::dd(uint32_t data) {
3583 // No relocation info should be pending while using dd. dd is used 3591 // No relocation info should be pending while using dd. dd is used
3584 // to write pure data with no pointers and the constant pool should 3592 // to write pure data with no pointers and the constant pool should
3585 // be emitted before using dd. 3593 // be emitted before using dd.
3586 DCHECK(num_pending_32_bit_constants_ == 0); 3594 DCHECK(num_pending_32_bit_reloc_info_ == 0);
3587 DCHECK(num_pending_64_bit_constants_ == 0); 3595 DCHECK(num_pending_64_bit_reloc_info_ == 0);
3588 CheckBuffer(); 3596 CheckBuffer();
3589 *reinterpret_cast<uint32_t*>(pc_) = data; 3597 *reinterpret_cast<uint32_t*>(pc_) = data;
3590 pc_ += sizeof(uint32_t); 3598 pc_ += sizeof(uint32_t);
3591 } 3599 }
3592 3600
3593 3601
3594 void Assembler::dq(uint64_t value) {
3595 // No relocation info should be pending while using dq. dq is used
3596 // to write pure data with no pointers and the constant pool should
3597 // be emitted before using dd.
3598 DCHECK(num_pending_32_bit_constants_ == 0);
3599 DCHECK(num_pending_64_bit_constants_ == 0);
3600 CheckBuffer();
3601 *reinterpret_cast<uint64_t*>(pc_) = value;
3602 pc_ += sizeof(uint64_t);
3603 }
3604
3605
3606 void Assembler::emit_code_stub_address(Code* stub) { 3602 void Assembler::emit_code_stub_address(Code* stub) {
3607 CheckBuffer(); 3603 CheckBuffer();
3608 *reinterpret_cast<uint32_t*>(pc_) = 3604 *reinterpret_cast<uint32_t*>(pc_) =
3609 reinterpret_cast<uint32_t>(stub->instruction_start()); 3605 reinterpret_cast<uint32_t>(stub->instruction_start());
3610 pc_ += sizeof(uint32_t); 3606 pc_ += sizeof(uint32_t);
3611 } 3607 }
3612 3608
3613 3609
3614 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { 3610 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
3615 if (RelocInfo::IsNone(rmode) ||
3616 // Don't record external references unless the heap will be serialized.
3617 (rmode == RelocInfo::EXTERNAL_REFERENCE && !serializer_enabled() &&
3618 !emit_debug_code())) {
3619 return;
3620 }
3621 DCHECK(buffer_space() >= kMaxRelocSize); // too late to grow buffer here
3622 if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
3623 data = RecordedAstId().ToInt();
3624 ClearRecordedAstId();
3625 }
3626 RelocInfo rinfo(pc_, rmode, data, NULL); 3611 RelocInfo rinfo(pc_, rmode, data, NULL);
3627 reloc_info_writer.Write(&rinfo); 3612 RecordRelocInfo(rinfo);
3628 } 3613 }
3629 3614
3630 3615
3631 ConstantPoolEntry::Access Assembler::ConstantPoolAddEntry(int position, 3616 void Assembler::RecordRelocInfo(const RelocInfo& rinfo) {
3632 RelocInfo::Mode rmode, 3617 if (!RelocInfo::IsNone(rinfo.rmode())) {
3633 intptr_t value) { 3618 // Don't record external references unless the heap will be serialized.
3634 DCHECK(rmode != RelocInfo::COMMENT && rmode != RelocInfo::POSITION && 3619 if (rinfo.rmode() == RelocInfo::EXTERNAL_REFERENCE &&
3635 rmode != RelocInfo::STATEMENT_POSITION && 3620 !serializer_enabled() && !emit_debug_code()) {
3636 rmode != RelocInfo::CONST_POOL && rmode != RelocInfo::NONE64); 3621 return;
3637 bool sharing_ok = RelocInfo::IsNone(rmode) ||
3638 !(serializer_enabled() || rmode < RelocInfo::CELL);
3639 if (FLAG_enable_embedded_constant_pool) {
3640 return constant_pool_builder_.AddEntry(position, value, sharing_ok);
3641 } else {
3642 DCHECK(num_pending_32_bit_constants_ < kMaxNumPending32Constants);
3643 if (num_pending_32_bit_constants_ == 0) {
3644 first_const_pool_32_use_ = position;
3645 } 3622 }
3646 ConstantPoolEntry entry(position, value, sharing_ok); 3623 DCHECK(buffer_space() >= kMaxRelocSize); // too late to grow buffer here
3647 pending_32_bit_constants_[num_pending_32_bit_constants_++] = entry; 3624 if (rinfo.rmode() == RelocInfo::CODE_TARGET_WITH_ID) {
3648 3625 RelocInfo reloc_info_with_ast_id(rinfo.pc(),
3649 // Make sure the constant pool is not emitted in place of the next 3626 rinfo.rmode(),
3650 // instruction for which we just recorded relocation info. 3627 RecordedAstId().ToInt(),
3651 BlockConstPoolFor(1); 3628 NULL);
3652 return ConstantPoolEntry::REGULAR; 3629 ClearRecordedAstId();
3630 reloc_info_writer.Write(&reloc_info_with_ast_id);
3631 } else {
3632 reloc_info_writer.Write(&rinfo);
3633 }
3653 } 3634 }
3654 } 3635 }
3655 3636
3656 3637
3657 ConstantPoolEntry::Access Assembler::ConstantPoolAddEntry(int position, 3638 ConstantPoolArray::LayoutSection Assembler::ConstantPoolAddEntry(
3658 double value) { 3639 const RelocInfo& rinfo) {
3659 if (FLAG_enable_embedded_constant_pool) { 3640 if (FLAG_enable_ool_constant_pool) {
3660 return constant_pool_builder_.AddEntry(position, value); 3641 return constant_pool_builder_.AddEntry(this, rinfo);
3661 } else { 3642 } else {
3662 DCHECK(num_pending_64_bit_constants_ < kMaxNumPending64Constants); 3643 if (rinfo.rmode() == RelocInfo::NONE64) {
3663 if (num_pending_64_bit_constants_ == 0) { 3644 DCHECK(num_pending_64_bit_reloc_info_ < kMaxNumPending64RelocInfo);
3664 first_const_pool_64_use_ = position; 3645 if (num_pending_64_bit_reloc_info_ == 0) {
3646 first_const_pool_64_use_ = pc_offset();
3647 }
3648 pending_64_bit_reloc_info_[num_pending_64_bit_reloc_info_++] = rinfo;
3649 } else {
3650 DCHECK(num_pending_32_bit_reloc_info_ < kMaxNumPending32RelocInfo);
3651 if (num_pending_32_bit_reloc_info_ == 0) {
3652 first_const_pool_32_use_ = pc_offset();
3653 }
3654 pending_32_bit_reloc_info_[num_pending_32_bit_reloc_info_++] = rinfo;
3665 } 3655 }
3666 ConstantPoolEntry entry(position, value);
3667 pending_64_bit_constants_[num_pending_64_bit_constants_++] = entry;
3668
3669 // Make sure the constant pool is not emitted in place of the next 3656 // Make sure the constant pool is not emitted in place of the next
3670 // instruction for which we just recorded relocation info. 3657 // instruction for which we just recorded relocation info.
3671 BlockConstPoolFor(1); 3658 BlockConstPoolFor(1);
3672 return ConstantPoolEntry::REGULAR; 3659 return ConstantPoolArray::SMALL_SECTION;
3673 } 3660 }
3674 } 3661 }
3675 3662
3676 3663
3677 void Assembler::BlockConstPoolFor(int instructions) { 3664 void Assembler::BlockConstPoolFor(int instructions) {
3678 if (FLAG_enable_embedded_constant_pool) { 3665 if (FLAG_enable_ool_constant_pool) {
3679 // Should be a no-op if using an embedded constant pool. 3666 // Should be a no-op if using an out-of-line constant pool.
3680 DCHECK(num_pending_32_bit_constants_ == 0); 3667 DCHECK(num_pending_32_bit_reloc_info_ == 0);
3681 DCHECK(num_pending_64_bit_constants_ == 0); 3668 DCHECK(num_pending_64_bit_reloc_info_ == 0);
3682 return; 3669 return;
3683 } 3670 }
3684 3671
3685 int pc_limit = pc_offset() + instructions * kInstrSize; 3672 int pc_limit = pc_offset() + instructions * kInstrSize;
3686 if (no_const_pool_before_ < pc_limit) { 3673 if (no_const_pool_before_ < pc_limit) {
3687 // Max pool start (if we need a jump and an alignment). 3674 // Max pool start (if we need a jump and an alignment).
3688 #ifdef DEBUG 3675 #ifdef DEBUG
3689 int start = pc_limit + kInstrSize + 2 * kPointerSize; 3676 int start = pc_limit + kInstrSize + 2 * kPointerSize;
3690 DCHECK((num_pending_32_bit_constants_ == 0) || 3677 DCHECK((num_pending_32_bit_reloc_info_ == 0) ||
3691 (start - first_const_pool_32_use_ + 3678 (start - first_const_pool_32_use_ +
3692 num_pending_64_bit_constants_ * kDoubleSize < 3679 num_pending_64_bit_reloc_info_ * kDoubleSize < kMaxDistToIntPool));
3693 kMaxDistToIntPool)); 3680 DCHECK((num_pending_64_bit_reloc_info_ == 0) ||
3694 DCHECK((num_pending_64_bit_constants_ == 0) ||
3695 (start - first_const_pool_64_use_ < kMaxDistToFPPool)); 3681 (start - first_const_pool_64_use_ < kMaxDistToFPPool));
3696 #endif 3682 #endif
3697 no_const_pool_before_ = pc_limit; 3683 no_const_pool_before_ = pc_limit;
3698 } 3684 }
3699 3685
3700 if (next_buffer_check_ < no_const_pool_before_) { 3686 if (next_buffer_check_ < no_const_pool_before_) {
3701 next_buffer_check_ = no_const_pool_before_; 3687 next_buffer_check_ = no_const_pool_before_;
3702 } 3688 }
3703 } 3689 }
3704 3690
3705 3691
3706 void Assembler::CheckConstPool(bool force_emit, bool require_jump) { 3692 void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
3707 if (FLAG_enable_embedded_constant_pool) { 3693 if (FLAG_enable_ool_constant_pool) {
3708 // Should be a no-op if using an embedded constant pool. 3694 // Should be a no-op if using an out-of-line constant pool.
3709 DCHECK(num_pending_32_bit_constants_ == 0); 3695 DCHECK(num_pending_32_bit_reloc_info_ == 0);
3710 DCHECK(num_pending_64_bit_constants_ == 0); 3696 DCHECK(num_pending_64_bit_reloc_info_ == 0);
3711 return; 3697 return;
3712 } 3698 }
3713 3699
3714 // Some short sequence of instruction mustn't be broken up by constant pool 3700 // Some short sequence of instruction mustn't be broken up by constant pool
3715 // emission, such sequences are protected by calls to BlockConstPoolFor and 3701 // emission, such sequences are protected by calls to BlockConstPoolFor and
3716 // BlockConstPoolScope. 3702 // BlockConstPoolScope.
3717 if (is_const_pool_blocked()) { 3703 if (is_const_pool_blocked()) {
3718 // Something is wrong if emission is forced and blocked at the same time. 3704 // Something is wrong if emission is forced and blocked at the same time.
3719 DCHECK(!force_emit); 3705 DCHECK(!force_emit);
3720 return; 3706 return;
3721 } 3707 }
3722 3708
3723 // There is nothing to do if there are no pending constant pool entries. 3709 // There is nothing to do if there are no pending constant pool entries.
3724 if ((num_pending_32_bit_constants_ == 0) && 3710 if ((num_pending_32_bit_reloc_info_ == 0) &&
3725 (num_pending_64_bit_constants_ == 0)) { 3711 (num_pending_64_bit_reloc_info_ == 0)) {
3726 // Calculate the offset of the next check. 3712 // Calculate the offset of the next check.
3727 next_buffer_check_ = pc_offset() + kCheckPoolInterval; 3713 next_buffer_check_ = pc_offset() + kCheckPoolInterval;
3728 return; 3714 return;
3729 } 3715 }
3730 3716
3731 // Check that the code buffer is large enough before emitting the constant 3717 // Check that the code buffer is large enough before emitting the constant
3732 // pool (include the jump over the pool and the constant pool marker and 3718 // pool (include the jump over the pool and the constant pool marker and
3733 // the gap to the relocation information). 3719 // the gap to the relocation information).
3734 int jump_instr = require_jump ? kInstrSize : 0; 3720 int jump_instr = require_jump ? kInstrSize : 0;
3735 int size_up_to_marker = jump_instr + kInstrSize; 3721 int size_up_to_marker = jump_instr + kInstrSize;
3736 int size_after_marker = num_pending_32_bit_constants_ * kPointerSize; 3722 int size_after_marker = num_pending_32_bit_reloc_info_ * kPointerSize;
3737 bool has_fp_values = (num_pending_64_bit_constants_ > 0); 3723 bool has_fp_values = (num_pending_64_bit_reloc_info_ > 0);
3738 bool require_64_bit_align = false; 3724 bool require_64_bit_align = false;
3739 if (has_fp_values) { 3725 if (has_fp_values) {
3740 require_64_bit_align = (((uintptr_t)pc_ + size_up_to_marker) & 0x7); 3726 require_64_bit_align = (((uintptr_t)pc_ + size_up_to_marker) & 0x7);
3741 if (require_64_bit_align) { 3727 if (require_64_bit_align) {
3742 size_after_marker += kInstrSize; 3728 size_after_marker += kInstrSize;
3743 } 3729 }
3744 size_after_marker += num_pending_64_bit_constants_ * kDoubleSize; 3730 size_after_marker += num_pending_64_bit_reloc_info_ * kDoubleSize;
3745 } 3731 }
3746 3732
3747 int size = size_up_to_marker + size_after_marker; 3733 int size = size_up_to_marker + size_after_marker;
3748 3734
3749 // We emit a constant pool when: 3735 // We emit a constant pool when:
3750 // * requested to do so by parameter force_emit (e.g. after each function). 3736 // * requested to do so by parameter force_emit (e.g. after each function).
3751 // * the distance from the first instruction accessing the constant pool to 3737 // * the distance from the first instruction accessing the constant pool to
3752 // any of the constant pool entries will exceed its limit the next 3738 // any of the constant pool entries will exceed its limit the next
3753 // time the pool is checked. This is overly restrictive, but we don't emit 3739 // time the pool is checked. This is overly restrictive, but we don't emit
3754 // constant pool entries in-order so it's conservatively correct. 3740 // constant pool entries in-order so it's conservatively correct.
3755 // * the instruction doesn't require a jump after itself to jump over the 3741 // * the instruction doesn't require a jump after itself to jump over the
3756 // constant pool, and we're getting close to running out of range. 3742 // constant pool, and we're getting close to running out of range.
3757 if (!force_emit) { 3743 if (!force_emit) {
3758 DCHECK((first_const_pool_32_use_ >= 0) || (first_const_pool_64_use_ >= 0)); 3744 DCHECK((first_const_pool_32_use_ >= 0) || (first_const_pool_64_use_ >= 0));
3759 bool need_emit = false; 3745 bool need_emit = false;
3760 if (has_fp_values) { 3746 if (has_fp_values) {
3761 int dist64 = pc_offset() + size - 3747 int dist64 = pc_offset() +
3762 num_pending_32_bit_constants_ * kPointerSize - 3748 size -
3749 num_pending_32_bit_reloc_info_ * kPointerSize -
3763 first_const_pool_64_use_; 3750 first_const_pool_64_use_;
3764 if ((dist64 >= kMaxDistToFPPool - kCheckPoolInterval) || 3751 if ((dist64 >= kMaxDistToFPPool - kCheckPoolInterval) ||
3765 (!require_jump && (dist64 >= kMaxDistToFPPool / 2))) { 3752 (!require_jump && (dist64 >= kMaxDistToFPPool / 2))) {
3766 need_emit = true; 3753 need_emit = true;
3767 } 3754 }
3768 } 3755 }
3769 int dist32 = 3756 int dist32 =
3770 pc_offset() + size - first_const_pool_32_use_; 3757 pc_offset() + size - first_const_pool_32_use_;
3771 if ((dist32 >= kMaxDistToIntPool - kCheckPoolInterval) || 3758 if ((dist32 >= kMaxDistToIntPool - kCheckPoolInterval) ||
3772 (!require_jump && (dist32 >= kMaxDistToIntPool / 2))) { 3759 (!require_jump && (dist32 >= kMaxDistToIntPool / 2))) {
(...skipping 21 matching lines...) Expand all
3794 // The data size helps disassembly know what to print. 3781 // The data size helps disassembly know what to print.
3795 emit(kConstantPoolMarker | 3782 emit(kConstantPoolMarker |
3796 EncodeConstantPoolLength(size_after_marker / kPointerSize)); 3783 EncodeConstantPoolLength(size_after_marker / kPointerSize));
3797 3784
3798 if (require_64_bit_align) { 3785 if (require_64_bit_align) {
3799 emit(kConstantPoolMarker); 3786 emit(kConstantPoolMarker);
3800 } 3787 }
3801 3788
3802 // Emit 64-bit constant pool entries first: their range is smaller than 3789 // Emit 64-bit constant pool entries first: their range is smaller than
3803 // 32-bit entries. 3790 // 32-bit entries.
3804 for (int i = 0; i < num_pending_64_bit_constants_; i++) { 3791 for (int i = 0; i < num_pending_64_bit_reloc_info_; i++) {
3805 ConstantPoolEntry& entry = pending_64_bit_constants_[i]; 3792 RelocInfo& rinfo = pending_64_bit_reloc_info_[i];
3806 3793
3807 DCHECK(!((uintptr_t)pc_ & 0x7)); // Check 64-bit alignment. 3794 DCHECK(!((uintptr_t)pc_ & 0x7)); // Check 64-bit alignment.
3808 3795
3809 Instr instr = instr_at(entry.position()); 3796 Instr instr = instr_at(rinfo.pc());
3810 // Instruction to patch must be 'vldr rd, [pc, #offset]' with offset == 0. 3797 // Instruction to patch must be 'vldr rd, [pc, #offset]' with offset == 0.
3811 DCHECK((IsVldrDPcImmediateOffset(instr) && 3798 DCHECK((IsVldrDPcImmediateOffset(instr) &&
3812 GetVldrDRegisterImmediateOffset(instr) == 0)); 3799 GetVldrDRegisterImmediateOffset(instr) == 0));
3813 3800
3814 int delta = pc_offset() - entry.position() - kPcLoadDelta; 3801 int delta = pc_ - rinfo.pc() - kPcLoadDelta;
3815 DCHECK(is_uint10(delta)); 3802 DCHECK(is_uint10(delta));
3816 3803
3817 bool found = false; 3804 bool found = false;
3818 uint64_t value = entry.value64(); 3805 uint64_t value = rinfo.raw_data64();
3819 for (int j = 0; j < i; j++) { 3806 for (int j = 0; j < i; j++) {
3820 ConstantPoolEntry& entry2 = pending_64_bit_constants_[j]; 3807 RelocInfo& rinfo2 = pending_64_bit_reloc_info_[j];
3821 if (value == entry2.value64()) { 3808 if (value == rinfo2.raw_data64()) {
3822 found = true; 3809 found = true;
3823 Instr instr2 = instr_at(entry2.position()); 3810 DCHECK(rinfo2.rmode() == RelocInfo::NONE64);
3811 Instr instr2 = instr_at(rinfo2.pc());
3824 DCHECK(IsVldrDPcImmediateOffset(instr2)); 3812 DCHECK(IsVldrDPcImmediateOffset(instr2));
3825 delta = GetVldrDRegisterImmediateOffset(instr2); 3813 delta = GetVldrDRegisterImmediateOffset(instr2);
3826 delta += entry2.position() - entry.position(); 3814 delta += rinfo2.pc() - rinfo.pc();
3827 break; 3815 break;
3828 } 3816 }
3829 } 3817 }
3830 3818
3831 instr_at_put(entry.position(), 3819 instr_at_put(rinfo.pc(), SetVldrDRegisterImmediateOffset(instr, delta));
3832 SetVldrDRegisterImmediateOffset(instr, delta));
3833 3820
3834 if (!found) { 3821 if (!found) {
3835 dq(entry.value64()); 3822 uint64_t uint_data = rinfo.raw_data64();
3823 emit(uint_data & 0xFFFFFFFF);
3824 emit(uint_data >> 32);
3836 } 3825 }
3837 } 3826 }
3838 3827
3839 // Emit 32-bit constant pool entries. 3828 // Emit 32-bit constant pool entries.
3840 for (int i = 0; i < num_pending_32_bit_constants_; i++) { 3829 for (int i = 0; i < num_pending_32_bit_reloc_info_; i++) {
3841 ConstantPoolEntry& entry = pending_32_bit_constants_[i]; 3830 RelocInfo& rinfo = pending_32_bit_reloc_info_[i];
3842 Instr instr = instr_at(entry.position()); 3831 DCHECK(rinfo.rmode() != RelocInfo::COMMENT &&
3832 rinfo.rmode() != RelocInfo::POSITION &&
3833 rinfo.rmode() != RelocInfo::STATEMENT_POSITION &&
3834 rinfo.rmode() != RelocInfo::CONST_POOL &&
3835 rinfo.rmode() != RelocInfo::NONE64);
3836
3837 Instr instr = instr_at(rinfo.pc());
3843 3838
3844 // 64-bit loads shouldn't get here. 3839 // 64-bit loads shouldn't get here.
3845 DCHECK(!IsVldrDPcImmediateOffset(instr)); 3840 DCHECK(!IsVldrDPcImmediateOffset(instr));
3846 3841
3847 if (IsLdrPcImmediateOffset(instr) && 3842 if (IsLdrPcImmediateOffset(instr) &&
3848 GetLdrRegisterImmediateOffset(instr) == 0) { 3843 GetLdrRegisterImmediateOffset(instr) == 0) {
3849 int delta = pc_offset() - entry.position() - kPcLoadDelta; 3844 int delta = pc_ - rinfo.pc() - kPcLoadDelta;
3850 DCHECK(is_uint12(delta)); 3845 DCHECK(is_uint12(delta));
3851 // 0 is the smallest delta: 3846 // 0 is the smallest delta:
3852 // ldr rd, [pc, #0] 3847 // ldr rd, [pc, #0]
3853 // constant pool marker 3848 // constant pool marker
3854 // data 3849 // data
3855 3850
3856 bool found = false; 3851 bool found = false;
3857 if (entry.sharing_ok()) { 3852 if (!serializer_enabled() && rinfo.rmode() >= RelocInfo::CELL) {
3858 for (int j = 0; j < i; j++) { 3853 for (int j = 0; j < i; j++) {
3859 ConstantPoolEntry& entry2 = pending_32_bit_constants_[j]; 3854 RelocInfo& rinfo2 = pending_32_bit_reloc_info_[j];
3860 3855
3861 if (entry2.value() == entry.value()) { 3856 if ((rinfo2.data() == rinfo.data()) &&
3862 Instr instr2 = instr_at(entry2.position()); 3857 (rinfo2.rmode() == rinfo.rmode())) {
3858 Instr instr2 = instr_at(rinfo2.pc());
3863 if (IsLdrPcImmediateOffset(instr2)) { 3859 if (IsLdrPcImmediateOffset(instr2)) {
3864 delta = GetLdrRegisterImmediateOffset(instr2); 3860 delta = GetLdrRegisterImmediateOffset(instr2);
3865 delta += entry2.position() - entry.position(); 3861 delta += rinfo2.pc() - rinfo.pc();
3866 found = true; 3862 found = true;
3867 break; 3863 break;
3868 } 3864 }
3869 } 3865 }
3870 } 3866 }
3871 } 3867 }
3872 3868
3873 instr_at_put(entry.position(), 3869 instr_at_put(rinfo.pc(), SetLdrRegisterImmediateOffset(instr, delta));
3874 SetLdrRegisterImmediateOffset(instr, delta));
3875 3870
3876 if (!found) { 3871 if (!found) {
3877 emit(entry.value()); 3872 emit(rinfo.data());
3878 } 3873 }
3879 } else { 3874 } else {
3880 DCHECK(IsMovW(instr)); 3875 DCHECK(IsMovW(instr));
3881 } 3876 }
3882 } 3877 }
3883 3878
3884 num_pending_32_bit_constants_ = 0; 3879 num_pending_32_bit_reloc_info_ = 0;
3885 num_pending_64_bit_constants_ = 0; 3880 num_pending_64_bit_reloc_info_ = 0;
3886 first_const_pool_32_use_ = -1; 3881 first_const_pool_32_use_ = -1;
3887 first_const_pool_64_use_ = -1; 3882 first_const_pool_64_use_ = -1;
3888 3883
3889 RecordComment("]"); 3884 RecordComment("]");
3890 3885
3891 if (after_pool.is_linked()) { 3886 if (after_pool.is_linked()) {
3892 bind(&after_pool); 3887 bind(&after_pool);
3893 } 3888 }
3894 } 3889 }
3895 3890
3896 // Since a constant pool was just emitted, move the check offset forward by 3891 // Since a constant pool was just emitted, move the check offset forward by
3897 // the standard interval. 3892 // the standard interval.
3898 next_buffer_check_ = pc_offset() + kCheckPoolInterval; 3893 next_buffer_check_ = pc_offset() + kCheckPoolInterval;
3899 } 3894 }
3900 3895
3901 3896
3902 void Assembler::PatchConstantPoolAccessInstruction( 3897 Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) {
3903 int pc_offset, int offset, ConstantPoolEntry::Access access, 3898 if (!FLAG_enable_ool_constant_pool) {
3904 ConstantPoolEntry::Type type) { 3899 return isolate->factory()->empty_constant_pool_array();
3905 DCHECK(FLAG_enable_embedded_constant_pool); 3900 }
3906 Address pc = buffer_ + pc_offset; 3901 return constant_pool_builder_.New(isolate);
3907 3902 }
3908 // Patch vldr/ldr instruction with correct offset. 3903
3909 Instr instr = instr_at(pc); 3904
3910 if (access == ConstantPoolEntry::OVERFLOWED) { 3905 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) {
3911 if (CpuFeatures::IsSupported(ARMv7)) { 3906 constant_pool_builder_.Populate(this, constant_pool);
3912 // Instructions to patch must be 'movw rd, [#0]' and 'movt rd, [#0]. 3907 }
3913 Instr next_instr = instr_at(pc + kInstrSize); 3908
3914 DCHECK((IsMovW(instr) && Instruction::ImmedMovwMovtValue(instr) == 0)); 3909
3915 DCHECK((IsMovT(next_instr) && 3910 ConstantPoolBuilder::ConstantPoolBuilder()
3916 Instruction::ImmedMovwMovtValue(next_instr) == 0)); 3911 : entries_(), current_section_(ConstantPoolArray::SMALL_SECTION) {}
3917 instr_at_put(pc, PatchMovwImmediate(instr, offset & 0xffff)); 3912
3918 instr_at_put(pc + kInstrSize, 3913
3919 PatchMovwImmediate(next_instr, offset >> 16)); 3914 bool ConstantPoolBuilder::IsEmpty() {
3915 return entries_.size() == 0;
3916 }
3917
3918
3919 ConstantPoolArray::Type ConstantPoolBuilder::GetConstantPoolType(
3920 RelocInfo::Mode rmode) {
3921 if (rmode == RelocInfo::NONE64) {
3922 return ConstantPoolArray::INT64;
3923 } else if (!RelocInfo::IsGCRelocMode(rmode)) {
3924 return ConstantPoolArray::INT32;
3925 } else if (RelocInfo::IsCodeTarget(rmode)) {
3926 return ConstantPoolArray::CODE_PTR;
3927 } else {
3928 DCHECK(RelocInfo::IsGCRelocMode(rmode) && !RelocInfo::IsCodeTarget(rmode));
3929 return ConstantPoolArray::HEAP_PTR;
3930 }
3931 }
3932
3933
3934 ConstantPoolArray::LayoutSection ConstantPoolBuilder::AddEntry(
3935 Assembler* assm, const RelocInfo& rinfo) {
3936 RelocInfo::Mode rmode = rinfo.rmode();
3937 DCHECK(rmode != RelocInfo::COMMENT &&
3938 rmode != RelocInfo::POSITION &&
3939 rmode != RelocInfo::STATEMENT_POSITION &&
3940 rmode != RelocInfo::CONST_POOL);
3941
3942 // Try to merge entries which won't be patched.
3943 int merged_index = -1;
3944 ConstantPoolArray::LayoutSection entry_section = current_section_;
3945 if (RelocInfo::IsNone(rmode) ||
3946 (!assm->serializer_enabled() && (rmode >= RelocInfo::CELL))) {
3947 size_t i;
3948 std::vector<ConstantPoolEntry>::const_iterator it;
3949 for (it = entries_.begin(), i = 0; it != entries_.end(); it++, i++) {
3950 if (RelocInfo::IsEqual(rinfo, it->rinfo_)) {
3951 // Merge with found entry.
3952 merged_index = i;
3953 entry_section = entries_[i].section_;
3954 break;
3955 }
3956 }
3957 }
3958 DCHECK(entry_section <= current_section_);
3959 entries_.push_back(ConstantPoolEntry(rinfo, entry_section, merged_index));
3960
3961 if (merged_index == -1) {
3962 // Not merged, so update the appropriate count.
3963 number_of_entries_[entry_section].increment(GetConstantPoolType(rmode));
3964 }
3965
3966 // Check if we still have room for another entry in the small section
3967 // given Arm's ldr and vldr immediate offset range.
3968 if (current_section_ == ConstantPoolArray::SMALL_SECTION &&
3969 !(is_uint12(ConstantPoolArray::SizeFor(*small_entries())) &&
3970 is_uint10(ConstantPoolArray::MaxInt64Offset(
3971 small_entries()->count_of(ConstantPoolArray::INT64))))) {
3972 current_section_ = ConstantPoolArray::EXTENDED_SECTION;
3973 }
3974 return entry_section;
3975 }
3976
3977
3978 void ConstantPoolBuilder::Relocate(int pc_delta) {
3979 for (std::vector<ConstantPoolEntry>::iterator entry = entries_.begin();
3980 entry != entries_.end(); entry++) {
3981 DCHECK(entry->rinfo_.rmode() != RelocInfo::JS_RETURN);
3982 entry->rinfo_.set_pc(entry->rinfo_.pc() + pc_delta);
3983 }
3984 }
3985
3986
3987 Handle<ConstantPoolArray> ConstantPoolBuilder::New(Isolate* isolate) {
3988 if (IsEmpty()) {
3989 return isolate->factory()->empty_constant_pool_array();
3990 } else if (extended_entries()->is_empty()) {
3991 return isolate->factory()->NewConstantPoolArray(*small_entries());
3992 } else {
3993 DCHECK(current_section_ == ConstantPoolArray::EXTENDED_SECTION);
3994 return isolate->factory()->NewExtendedConstantPoolArray(
3995 *small_entries(), *extended_entries());
3996 }
3997 }
3998
3999
4000 void ConstantPoolBuilder::Populate(Assembler* assm,
4001 ConstantPoolArray* constant_pool) {
4002 DCHECK_EQ(extended_entries()->is_empty(),
4003 !constant_pool->is_extended_layout());
4004 DCHECK(small_entries()->equals(ConstantPoolArray::NumberOfEntries(
4005 constant_pool, ConstantPoolArray::SMALL_SECTION)));
4006 if (constant_pool->is_extended_layout()) {
4007 DCHECK(extended_entries()->equals(ConstantPoolArray::NumberOfEntries(
4008 constant_pool, ConstantPoolArray::EXTENDED_SECTION)));
4009 }
4010
4011 // Set up initial offsets.
4012 int offsets[ConstantPoolArray::NUMBER_OF_LAYOUT_SECTIONS]
4013 [ConstantPoolArray::NUMBER_OF_TYPES];
4014 for (int section = 0; section <= constant_pool->final_section(); section++) {
4015 int section_start = (section == ConstantPoolArray::EXTENDED_SECTION)
4016 ? small_entries()->total_count()
4017 : 0;
4018 for (int i = 0; i < ConstantPoolArray::NUMBER_OF_TYPES; i++) {
4019 ConstantPoolArray::Type type = static_cast<ConstantPoolArray::Type>(i);
4020 if (number_of_entries_[section].count_of(type) != 0) {
4021 offsets[section][type] = constant_pool->OffsetOfElementAt(
4022 number_of_entries_[section].base_of(type) + section_start);
4023 }
4024 }
4025 }
4026
4027 for (std::vector<ConstantPoolEntry>::iterator entry = entries_.begin();
4028 entry != entries_.end(); entry++) {
4029 RelocInfo rinfo = entry->rinfo_;
4030 RelocInfo::Mode rmode = entry->rinfo_.rmode();
4031 ConstantPoolArray::Type type = GetConstantPoolType(rmode);
4032
4033 // Update constant pool if necessary and get the entry's offset.
4034 int offset;
4035 if (entry->merged_index_ == -1) {
4036 offset = offsets[entry->section_][type];
4037 offsets[entry->section_][type] += ConstantPoolArray::entry_size(type);
4038 if (type == ConstantPoolArray::INT64) {
4039 constant_pool->set_at_offset(offset, rinfo.data64());
4040 } else if (type == ConstantPoolArray::INT32) {
4041 constant_pool->set_at_offset(offset,
4042 static_cast<int32_t>(rinfo.data()));
4043 } else if (type == ConstantPoolArray::CODE_PTR) {
4044 constant_pool->set_at_offset(offset,
4045 reinterpret_cast<Address>(rinfo.data()));
4046 } else {
4047 DCHECK(type == ConstantPoolArray::HEAP_PTR);
4048 constant_pool->set_at_offset(offset,
4049 reinterpret_cast<Object*>(rinfo.data()));
4050 }
4051 offset -= kHeapObjectTag;
4052 entry->merged_index_ = offset; // Stash offset for merged entries.
3920 } else { 4053 } else {
3921 // Instructions to patch must be 'mov rd, [#0]' and 'orr rd, rd, [#0]. 4054 DCHECK(entry->merged_index_ < (entry - entries_.begin()));
3922 Instr instr_2 = instr_at(pc + kInstrSize); 4055 offset = entries_[entry->merged_index_].merged_index_;
3923 Instr instr_3 = instr_at(pc + 2 * kInstrSize); 4056 }
3924 Instr instr_4 = instr_at(pc + 3 * kInstrSize); 4057
3925 DCHECK((IsMovImmed(instr) && Instruction::Immed8Value(instr) == 0)); 4058 // Patch vldr/ldr instruction with correct offset.
3926 DCHECK((IsOrrImmed(instr_2) && Instruction::Immed8Value(instr_2) == 0) && 4059 Instr instr = assm->instr_at(rinfo.pc());
3927 GetRn(instr_2).is(GetRd(instr_2))); 4060 if (entry->section_ == ConstantPoolArray::EXTENDED_SECTION) {
3928 DCHECK((IsOrrImmed(instr_3) && Instruction::Immed8Value(instr_3) == 0) && 4061 if (CpuFeatures::IsSupported(ARMv7)) {
3929 GetRn(instr_3).is(GetRd(instr_3))); 4062 // Instructions to patch must be 'movw rd, [#0]' and 'movt rd, [#0].
3930 DCHECK((IsOrrImmed(instr_4) && Instruction::Immed8Value(instr_4) == 0) && 4063 Instr next_instr = assm->instr_at(rinfo.pc() + Assembler::kInstrSize);
3931 GetRn(instr_4).is(GetRd(instr_4))); 4064 DCHECK((Assembler::IsMovW(instr) &&
3932 instr_at_put(pc, PatchShiftImm(instr, (offset & kImm8Mask))); 4065 Instruction::ImmedMovwMovtValue(instr) == 0));
3933 instr_at_put(pc + kInstrSize, 4066 DCHECK((Assembler::IsMovT(next_instr) &&
3934 PatchShiftImm(instr_2, (offset & (kImm8Mask << 8)))); 4067 Instruction::ImmedMovwMovtValue(next_instr) == 0));
3935 instr_at_put(pc + 2 * kInstrSize, 4068 assm->instr_at_put(
3936 PatchShiftImm(instr_3, (offset & (kImm8Mask << 16)))); 4069 rinfo.pc(), Assembler::PatchMovwImmediate(instr, offset & 0xffff));
3937 instr_at_put(pc + 3 * kInstrSize, 4070 assm->instr_at_put(
3938 PatchShiftImm(instr_4, (offset & (kImm8Mask << 24)))); 4071 rinfo.pc() + Assembler::kInstrSize,
3939 } 4072 Assembler::PatchMovwImmediate(next_instr, offset >> 16));
3940 } else if (type == ConstantPoolEntry::DOUBLE) { 4073 } else {
3941 // Instruction to patch must be 'vldr rd, [pp, #0]'. 4074 // Instructions to patch must be 'mov rd, [#0]' and 'orr rd, rd, [#0].
3942 DCHECK((IsVldrDPpImmediateOffset(instr) && 4075 Instr instr_2 = assm->instr_at(rinfo.pc() + Assembler::kInstrSize);
3943 GetVldrDRegisterImmediateOffset(instr) == 0)); 4076 Instr instr_3 = assm->instr_at(rinfo.pc() + 2 * Assembler::kInstrSize);
3944 DCHECK(is_uint10(offset)); 4077 Instr instr_4 = assm->instr_at(rinfo.pc() + 3 * Assembler::kInstrSize);
3945 instr_at_put(pc, SetVldrDRegisterImmediateOffset(instr, offset)); 4078 DCHECK((Assembler::IsMovImmed(instr) &&
3946 } else { 4079 Instruction::Immed8Value(instr) == 0));
3947 // Instruction to patch must be 'ldr rd, [pp, #0]'. 4080 DCHECK((Assembler::IsOrrImmed(instr_2) &&
3948 DCHECK((IsLdrPpImmediateOffset(instr) && 4081 Instruction::Immed8Value(instr_2) == 0) &&
3949 GetLdrRegisterImmediateOffset(instr) == 0)); 4082 Assembler::GetRn(instr_2).is(Assembler::GetRd(instr_2)));
3950 DCHECK(is_uint12(offset)); 4083 DCHECK((Assembler::IsOrrImmed(instr_3) &&
3951 instr_at_put(pc, SetLdrRegisterImmediateOffset(instr, offset)); 4084 Instruction::Immed8Value(instr_3) == 0) &&
3952 } 4085 Assembler::GetRn(instr_3).is(Assembler::GetRd(instr_3)));
3953 } 4086 DCHECK((Assembler::IsOrrImmed(instr_4) &&
3954 4087 Instruction::Immed8Value(instr_4) == 0) &&
4088 Assembler::GetRn(instr_4).is(Assembler::GetRd(instr_4)));
4089 assm->instr_at_put(
4090 rinfo.pc(), Assembler::PatchShiftImm(instr, (offset & kImm8Mask)));
4091 assm->instr_at_put(
4092 rinfo.pc() + Assembler::kInstrSize,
4093 Assembler::PatchShiftImm(instr_2, (offset & (kImm8Mask << 8))));
4094 assm->instr_at_put(
4095 rinfo.pc() + 2 * Assembler::kInstrSize,
4096 Assembler::PatchShiftImm(instr_3, (offset & (kImm8Mask << 16))));
4097 assm->instr_at_put(
4098 rinfo.pc() + 3 * Assembler::kInstrSize,
4099 Assembler::PatchShiftImm(instr_4, (offset & (kImm8Mask << 24))));
4100 }
4101 } else if (type == ConstantPoolArray::INT64) {
4102 // Instruction to patch must be 'vldr rd, [pp, #0]'.
4103 DCHECK((Assembler::IsVldrDPpImmediateOffset(instr) &&
4104 Assembler::GetVldrDRegisterImmediateOffset(instr) == 0));
4105 DCHECK(is_uint10(offset));
4106 assm->instr_at_put(rinfo.pc(), Assembler::SetVldrDRegisterImmediateOffset(
4107 instr, offset));
4108 } else {
4109 // Instruction to patch must be 'ldr rd, [pp, #0]'.
4110 DCHECK((Assembler::IsLdrPpImmediateOffset(instr) &&
4111 Assembler::GetLdrRegisterImmediateOffset(instr) == 0));
4112 DCHECK(is_uint12(offset));
4113 assm->instr_at_put(
4114 rinfo.pc(), Assembler::SetLdrRegisterImmediateOffset(instr, offset));
4115 }
4116 }
4117 }
4118
3955 4119
3956 } // namespace internal 4120 } // namespace internal
3957 } // namespace v8 4121 } // namespace v8
3958 4122
3959 #endif // V8_TARGET_ARCH_ARM 4123 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/assembler-arm.h ('k') | src/arm/assembler-arm-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698