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

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

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

Powered by Google App Engine
This is Rietveld 408576698