| Index: src/arm/assembler-arm.cc
|
| diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
|
| index ed8664a9c5f32f10ddc131ad8973e2b79cc37347..315eeb1b66a69c85241d10857de6e95515b8364a 100644
|
| --- a/src/arm/assembler-arm.cc
|
| +++ b/src/arm/assembler-arm.cc
|
| @@ -234,9 +234,9 @@
|
| bool RelocInfo::IsCodedSpecially() {
|
| // The deserializer needs to know whether a pointer is specially coded. Being
|
| // specially coded on ARM means that it is a movw/movt instruction, or is an
|
| - // embedded constant pool entry. These only occur if
|
| - // FLAG_enable_embedded_constant_pool is true.
|
| - return FLAG_enable_embedded_constant_pool;
|
| + // out of line constant pool entry. These only occur if
|
| + // FLAG_enable_ool_constant_pool is true.
|
| + return FLAG_enable_ool_constant_pool;
|
| }
|
|
|
|
|
| @@ -449,11 +449,11 @@
|
| Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
|
| : AssemblerBase(isolate, buffer, buffer_size),
|
| recorded_ast_id_(TypeFeedbackId::None()),
|
| - constant_pool_builder_(kLdrMaxReachBits, kVldrMaxReachBits),
|
| + constant_pool_builder_(),
|
| positions_recorder_(this) {
|
| reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
|
| - num_pending_32_bit_constants_ = 0;
|
| - num_pending_64_bit_constants_ = 0;
|
| + num_pending_32_bit_reloc_info_ = 0;
|
| + num_pending_64_bit_reloc_info_ = 0;
|
| next_buffer_check_ = 0;
|
| const_pool_blocked_nesting_ = 0;
|
| no_const_pool_before_ = 0;
|
| @@ -471,23 +471,17 @@
|
|
|
| void Assembler::GetCode(CodeDesc* desc) {
|
| reloc_info_writer.Finish();
|
| -
|
| - // Emit constant pool if necessary.
|
| - int constant_pool_offset = 0;
|
| - if (FLAG_enable_embedded_constant_pool) {
|
| - constant_pool_offset = EmitEmbeddedConstantPool();
|
| - } else {
|
| + if (!FLAG_enable_ool_constant_pool) {
|
| + // Emit constant pool if necessary.
|
| CheckConstPool(true, false);
|
| - DCHECK(num_pending_32_bit_constants_ == 0);
|
| - DCHECK(num_pending_64_bit_constants_ == 0);
|
| + DCHECK(num_pending_32_bit_reloc_info_ == 0);
|
| + DCHECK(num_pending_64_bit_reloc_info_ == 0);
|
| }
|
| // Set up code descriptor.
|
| desc->buffer = buffer_;
|
| desc->buffer_size = buffer_size_;
|
| desc->instr_size = pc_offset();
|
| desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
|
| - desc->constant_pool_size =
|
| - (constant_pool_offset ? desc->instr_size - constant_pool_offset : 0);
|
| desc->origin = this;
|
| }
|
|
|
| @@ -629,7 +623,7 @@
|
|
|
|
|
| Instr Assembler::GetConsantPoolLoadPattern() {
|
| - if (FLAG_enable_embedded_constant_pool) {
|
| + if (FLAG_enable_ool_constant_pool) {
|
| return kLdrPpImmedPattern;
|
| } else {
|
| return kLdrPCImmedPattern;
|
| @@ -638,7 +632,7 @@
|
|
|
|
|
| Instr Assembler::GetConsantPoolLoadMask() {
|
| - if (FLAG_enable_embedded_constant_pool) {
|
| + if (FLAG_enable_ool_constant_pool) {
|
| return kLdrPpImmedMask;
|
| } else {
|
| return kLdrPCImmedMask;
|
| @@ -1050,8 +1044,8 @@
|
|
|
| static bool use_mov_immediate_load(const Operand& x,
|
| const Assembler* assembler) {
|
| - if (FLAG_enable_embedded_constant_pool && assembler != NULL &&
|
| - !assembler->is_constant_pool_available()) {
|
| + if (FLAG_enable_ool_constant_pool && assembler != NULL &&
|
| + !assembler->is_ool_constant_pool_available()) {
|
| return true;
|
| } else if (CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) &&
|
| (assembler == NULL || !assembler->predictable_code_size())) {
|
| @@ -1080,9 +1074,8 @@
|
| if (use_mov_immediate_load(*this, assembler)) {
|
| // A movw / movt or mov / orr immediate load.
|
| instructions = CpuFeatures::IsSupported(ARMv7) ? 2 : 4;
|
| - } else if (assembler != NULL &&
|
| - assembler->ConstantPoolAccessIsInOverflow()) {
|
| - // An overflowed constant pool load.
|
| + } else if (assembler != NULL && assembler->use_extended_constant_pool()) {
|
| + // An extended constant pool load.
|
| instructions = CpuFeatures::IsSupported(ARMv7) ? 3 : 5;
|
| } else {
|
| // A small constant pool load.
|
| @@ -1107,23 +1100,23 @@
|
| void Assembler::move_32_bit_immediate(Register rd,
|
| const Operand& x,
|
| Condition cond) {
|
| + RelocInfo rinfo(pc_, x.rmode_, x.imm32_, NULL);
|
| uint32_t imm32 = static_cast<uint32_t>(x.imm32_);
|
| if (x.must_output_reloc_info(this)) {
|
| - RecordRelocInfo(x.rmode_);
|
| + RecordRelocInfo(rinfo);
|
| }
|
|
|
| if (use_mov_immediate_load(x, this)) {
|
| Register target = rd.code() == pc.code() ? ip : rd;
|
| if (CpuFeatures::IsSupported(ARMv7)) {
|
| - if (!FLAG_enable_embedded_constant_pool &&
|
| - x.must_output_reloc_info(this)) {
|
| + if (!FLAG_enable_ool_constant_pool && x.must_output_reloc_info(this)) {
|
| // Make sure the movw/movt doesn't get separated.
|
| BlockConstPoolFor(2);
|
| }
|
| movw(target, imm32 & 0xffff, cond);
|
| movt(target, imm32 >> 16, cond);
|
| } else {
|
| - DCHECK(FLAG_enable_embedded_constant_pool);
|
| + DCHECK(FLAG_enable_ool_constant_pool);
|
| mov(target, Operand(imm32 & kImm8Mask), LeaveCC, cond);
|
| orr(target, target, Operand(imm32 & (kImm8Mask << 8)), LeaveCC, cond);
|
| orr(target, target, Operand(imm32 & (kImm8Mask << 16)), LeaveCC, cond);
|
| @@ -1133,11 +1126,10 @@
|
| mov(rd, target, LeaveCC, cond);
|
| }
|
| } else {
|
| - DCHECK(!FLAG_enable_embedded_constant_pool || is_constant_pool_available());
|
| - ConstantPoolEntry::Access access =
|
| - ConstantPoolAddEntry(pc_offset(), x.rmode_, x.imm32_);
|
| - if (access == ConstantPoolEntry::OVERFLOWED) {
|
| - DCHECK(FLAG_enable_embedded_constant_pool);
|
| + DCHECK(!FLAG_enable_ool_constant_pool || is_ool_constant_pool_available());
|
| + ConstantPoolArray::LayoutSection section = ConstantPoolAddEntry(rinfo);
|
| + if (section == ConstantPoolArray::EXTENDED_SECTION) {
|
| + DCHECK(FLAG_enable_ool_constant_pool);
|
| Register target = rd.code() == pc.code() ? ip : rd;
|
| // Emit instructions to load constant pool offset.
|
| if (CpuFeatures::IsSupported(ARMv7)) {
|
| @@ -1152,9 +1144,8 @@
|
| // Load from constant pool at offset.
|
| ldr(rd, MemOperand(pp, target), cond);
|
| } else {
|
| - DCHECK(access == ConstantPoolEntry::REGULAR);
|
| - ldr(rd, MemOperand(FLAG_enable_embedded_constant_pool ? pp : pc, 0),
|
| - cond);
|
| + DCHECK(section == ConstantPoolArray::SMALL_SECTION);
|
| + ldr(rd, MemOperand(FLAG_enable_ool_constant_pool ? pp : pc, 0), cond);
|
| }
|
| }
|
| }
|
| @@ -2563,7 +2554,7 @@
|
| int vd, d;
|
| dst.split_code(&vd, &d);
|
| emit(al | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | enc);
|
| - } else if (FLAG_enable_vldr_imm && is_constant_pool_available()) {
|
| + } else if (FLAG_enable_vldr_imm && is_ool_constant_pool_available()) {
|
| // TODO(jfb) Temporarily turned off until we have constant blinding or
|
| // some equivalent mitigation: an attacker can otherwise control
|
| // generated data which also happens to be executable, a Very Bad
|
| @@ -2579,17 +2570,18 @@
|
| // The code could also randomize the order of values, though
|
| // that's tricky because vldr has a limited reach. Furthermore
|
| // it breaks load locality.
|
| - ConstantPoolEntry::Access access = ConstantPoolAddEntry(pc_offset(), imm);
|
| - if (access == ConstantPoolEntry::OVERFLOWED) {
|
| - DCHECK(FLAG_enable_embedded_constant_pool);
|
| + RelocInfo rinfo(pc_, imm);
|
| + ConstantPoolArray::LayoutSection section = ConstantPoolAddEntry(rinfo);
|
| + if (section == ConstantPoolArray::EXTENDED_SECTION) {
|
| + DCHECK(FLAG_enable_ool_constant_pool);
|
| // Emit instructions to load constant pool offset.
|
| movw(ip, 0);
|
| movt(ip, 0);
|
| // Load from constant pool at offset.
|
| vldr(dst, MemOperand(pp, ip));
|
| } else {
|
| - DCHECK(access == ConstantPoolEntry::REGULAR);
|
| - vldr(dst, MemOperand(FLAG_enable_embedded_constant_pool ? pp : pc, 0));
|
| + DCHECK(section == ConstantPoolArray::SMALL_SECTION);
|
| + vldr(dst, MemOperand(FLAG_enable_ool_constant_pool ? pp : pc, 0));
|
| }
|
| } else {
|
| // Synthesise the double from ARM immediates.
|
| @@ -3564,6 +3556,22 @@
|
| // None of our relocation types are pc relative pointing outside the code
|
| // buffer nor pc absolute pointing inside the code buffer, so there is no need
|
| // to relocate any emitted relocation entries.
|
| +
|
| + // Relocate pending relocation entries.
|
| + for (int i = 0; i < num_pending_32_bit_reloc_info_; i++) {
|
| + RelocInfo& rinfo = pending_32_bit_reloc_info_[i];
|
| + DCHECK(rinfo.rmode() != RelocInfo::COMMENT &&
|
| + rinfo.rmode() != RelocInfo::POSITION);
|
| + if (rinfo.rmode() != RelocInfo::JS_RETURN) {
|
| + rinfo.set_pc(rinfo.pc() + pc_delta);
|
| + }
|
| + }
|
| + for (int i = 0; i < num_pending_64_bit_reloc_info_; i++) {
|
| + RelocInfo& rinfo = pending_64_bit_reloc_info_[i];
|
| + DCHECK(rinfo.rmode() == RelocInfo::NONE64);
|
| + rinfo.set_pc(rinfo.pc() + pc_delta);
|
| + }
|
| + constant_pool_builder_.Relocate(pc_delta);
|
| }
|
|
|
|
|
| @@ -3571,8 +3579,8 @@
|
| // No relocation info should be pending while using db. db is used
|
| // to write pure data with no pointers and the constant pool should
|
| // be emitted before using db.
|
| - DCHECK(num_pending_32_bit_constants_ == 0);
|
| - DCHECK(num_pending_64_bit_constants_ == 0);
|
| + DCHECK(num_pending_32_bit_reloc_info_ == 0);
|
| + DCHECK(num_pending_64_bit_reloc_info_ == 0);
|
| CheckBuffer();
|
| *reinterpret_cast<uint8_t*>(pc_) = data;
|
| pc_ += sizeof(uint8_t);
|
| @@ -3583,23 +3591,11 @@
|
| // No relocation info should be pending while using dd. dd is used
|
| // to write pure data with no pointers and the constant pool should
|
| // be emitted before using dd.
|
| - DCHECK(num_pending_32_bit_constants_ == 0);
|
| - DCHECK(num_pending_64_bit_constants_ == 0);
|
| + DCHECK(num_pending_32_bit_reloc_info_ == 0);
|
| + DCHECK(num_pending_64_bit_reloc_info_ == 0);
|
| CheckBuffer();
|
| *reinterpret_cast<uint32_t*>(pc_) = data;
|
| pc_ += sizeof(uint32_t);
|
| -}
|
| -
|
| -
|
| -void Assembler::dq(uint64_t value) {
|
| - // No relocation info should be pending while using dq. dq is used
|
| - // to write pure data with no pointers and the constant pool should
|
| - // be emitted before using dd.
|
| - DCHECK(num_pending_32_bit_constants_ == 0);
|
| - DCHECK(num_pending_64_bit_constants_ == 0);
|
| - CheckBuffer();
|
| - *reinterpret_cast<uint64_t*>(pc_) = value;
|
| - pc_ += sizeof(uint64_t);
|
| }
|
|
|
|
|
| @@ -3612,73 +3608,64 @@
|
|
|
|
|
| void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
|
| - if (RelocInfo::IsNone(rmode) ||
|
| - // Don't record external references unless the heap will be serialized.
|
| - (rmode == RelocInfo::EXTERNAL_REFERENCE && !serializer_enabled() &&
|
| - !emit_debug_code())) {
|
| - return;
|
| - }
|
| - DCHECK(buffer_space() >= kMaxRelocSize); // too late to grow buffer here
|
| - if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
|
| - data = RecordedAstId().ToInt();
|
| - ClearRecordedAstId();
|
| - }
|
| RelocInfo rinfo(pc_, rmode, data, NULL);
|
| - reloc_info_writer.Write(&rinfo);
|
| -}
|
| -
|
| -
|
| -ConstantPoolEntry::Access Assembler::ConstantPoolAddEntry(int position,
|
| - RelocInfo::Mode rmode,
|
| - intptr_t value) {
|
| - DCHECK(rmode != RelocInfo::COMMENT && rmode != RelocInfo::POSITION &&
|
| - rmode != RelocInfo::STATEMENT_POSITION &&
|
| - rmode != RelocInfo::CONST_POOL && rmode != RelocInfo::NONE64);
|
| - bool sharing_ok = RelocInfo::IsNone(rmode) ||
|
| - !(serializer_enabled() || rmode < RelocInfo::CELL);
|
| - if (FLAG_enable_embedded_constant_pool) {
|
| - return constant_pool_builder_.AddEntry(position, value, sharing_ok);
|
| + RecordRelocInfo(rinfo);
|
| +}
|
| +
|
| +
|
| +void Assembler::RecordRelocInfo(const RelocInfo& rinfo) {
|
| + if (!RelocInfo::IsNone(rinfo.rmode())) {
|
| + // Don't record external references unless the heap will be serialized.
|
| + if (rinfo.rmode() == RelocInfo::EXTERNAL_REFERENCE &&
|
| + !serializer_enabled() && !emit_debug_code()) {
|
| + return;
|
| + }
|
| + DCHECK(buffer_space() >= kMaxRelocSize); // too late to grow buffer here
|
| + if (rinfo.rmode() == RelocInfo::CODE_TARGET_WITH_ID) {
|
| + RelocInfo reloc_info_with_ast_id(rinfo.pc(),
|
| + rinfo.rmode(),
|
| + RecordedAstId().ToInt(),
|
| + NULL);
|
| + ClearRecordedAstId();
|
| + reloc_info_writer.Write(&reloc_info_with_ast_id);
|
| + } else {
|
| + reloc_info_writer.Write(&rinfo);
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +ConstantPoolArray::LayoutSection Assembler::ConstantPoolAddEntry(
|
| + const RelocInfo& rinfo) {
|
| + if (FLAG_enable_ool_constant_pool) {
|
| + return constant_pool_builder_.AddEntry(this, rinfo);
|
| } else {
|
| - DCHECK(num_pending_32_bit_constants_ < kMaxNumPending32Constants);
|
| - if (num_pending_32_bit_constants_ == 0) {
|
| - first_const_pool_32_use_ = position;
|
| - }
|
| - ConstantPoolEntry entry(position, value, sharing_ok);
|
| - pending_32_bit_constants_[num_pending_32_bit_constants_++] = entry;
|
| -
|
| + if (rinfo.rmode() == RelocInfo::NONE64) {
|
| + DCHECK(num_pending_64_bit_reloc_info_ < kMaxNumPending64RelocInfo);
|
| + if (num_pending_64_bit_reloc_info_ == 0) {
|
| + first_const_pool_64_use_ = pc_offset();
|
| + }
|
| + pending_64_bit_reloc_info_[num_pending_64_bit_reloc_info_++] = rinfo;
|
| + } else {
|
| + DCHECK(num_pending_32_bit_reloc_info_ < kMaxNumPending32RelocInfo);
|
| + if (num_pending_32_bit_reloc_info_ == 0) {
|
| + first_const_pool_32_use_ = pc_offset();
|
| + }
|
| + pending_32_bit_reloc_info_[num_pending_32_bit_reloc_info_++] = rinfo;
|
| + }
|
| // Make sure the constant pool is not emitted in place of the next
|
| // instruction for which we just recorded relocation info.
|
| BlockConstPoolFor(1);
|
| - return ConstantPoolEntry::REGULAR;
|
| - }
|
| -}
|
| -
|
| -
|
| -ConstantPoolEntry::Access Assembler::ConstantPoolAddEntry(int position,
|
| - double value) {
|
| - if (FLAG_enable_embedded_constant_pool) {
|
| - return constant_pool_builder_.AddEntry(position, value);
|
| - } else {
|
| - DCHECK(num_pending_64_bit_constants_ < kMaxNumPending64Constants);
|
| - if (num_pending_64_bit_constants_ == 0) {
|
| - first_const_pool_64_use_ = position;
|
| - }
|
| - ConstantPoolEntry entry(position, value);
|
| - pending_64_bit_constants_[num_pending_64_bit_constants_++] = entry;
|
| -
|
| - // Make sure the constant pool is not emitted in place of the next
|
| - // instruction for which we just recorded relocation info.
|
| - BlockConstPoolFor(1);
|
| - return ConstantPoolEntry::REGULAR;
|
| + return ConstantPoolArray::SMALL_SECTION;
|
| }
|
| }
|
|
|
|
|
| void Assembler::BlockConstPoolFor(int instructions) {
|
| - if (FLAG_enable_embedded_constant_pool) {
|
| - // Should be a no-op if using an embedded constant pool.
|
| - DCHECK(num_pending_32_bit_constants_ == 0);
|
| - DCHECK(num_pending_64_bit_constants_ == 0);
|
| + if (FLAG_enable_ool_constant_pool) {
|
| + // Should be a no-op if using an out-of-line constant pool.
|
| + DCHECK(num_pending_32_bit_reloc_info_ == 0);
|
| + DCHECK(num_pending_64_bit_reloc_info_ == 0);
|
| return;
|
| }
|
|
|
| @@ -3687,11 +3674,10 @@
|
| // Max pool start (if we need a jump and an alignment).
|
| #ifdef DEBUG
|
| int start = pc_limit + kInstrSize + 2 * kPointerSize;
|
| - DCHECK((num_pending_32_bit_constants_ == 0) ||
|
| + DCHECK((num_pending_32_bit_reloc_info_ == 0) ||
|
| (start - first_const_pool_32_use_ +
|
| - num_pending_64_bit_constants_ * kDoubleSize <
|
| - kMaxDistToIntPool));
|
| - DCHECK((num_pending_64_bit_constants_ == 0) ||
|
| + num_pending_64_bit_reloc_info_ * kDoubleSize < kMaxDistToIntPool));
|
| + DCHECK((num_pending_64_bit_reloc_info_ == 0) ||
|
| (start - first_const_pool_64_use_ < kMaxDistToFPPool));
|
| #endif
|
| no_const_pool_before_ = pc_limit;
|
| @@ -3704,10 +3690,10 @@
|
|
|
|
|
| void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
|
| - if (FLAG_enable_embedded_constant_pool) {
|
| - // Should be a no-op if using an embedded constant pool.
|
| - DCHECK(num_pending_32_bit_constants_ == 0);
|
| - DCHECK(num_pending_64_bit_constants_ == 0);
|
| + if (FLAG_enable_ool_constant_pool) {
|
| + // Should be a no-op if using an out-of-line constant pool.
|
| + DCHECK(num_pending_32_bit_reloc_info_ == 0);
|
| + DCHECK(num_pending_64_bit_reloc_info_ == 0);
|
| return;
|
| }
|
|
|
| @@ -3721,8 +3707,8 @@
|
| }
|
|
|
| // There is nothing to do if there are no pending constant pool entries.
|
| - if ((num_pending_32_bit_constants_ == 0) &&
|
| - (num_pending_64_bit_constants_ == 0)) {
|
| + if ((num_pending_32_bit_reloc_info_ == 0) &&
|
| + (num_pending_64_bit_reloc_info_ == 0)) {
|
| // Calculate the offset of the next check.
|
| next_buffer_check_ = pc_offset() + kCheckPoolInterval;
|
| return;
|
| @@ -3733,15 +3719,15 @@
|
| // the gap to the relocation information).
|
| int jump_instr = require_jump ? kInstrSize : 0;
|
| int size_up_to_marker = jump_instr + kInstrSize;
|
| - int size_after_marker = num_pending_32_bit_constants_ * kPointerSize;
|
| - bool has_fp_values = (num_pending_64_bit_constants_ > 0);
|
| + int size_after_marker = num_pending_32_bit_reloc_info_ * kPointerSize;
|
| + bool has_fp_values = (num_pending_64_bit_reloc_info_ > 0);
|
| bool require_64_bit_align = false;
|
| if (has_fp_values) {
|
| require_64_bit_align = (((uintptr_t)pc_ + size_up_to_marker) & 0x7);
|
| if (require_64_bit_align) {
|
| size_after_marker += kInstrSize;
|
| }
|
| - size_after_marker += num_pending_64_bit_constants_ * kDoubleSize;
|
| + size_after_marker += num_pending_64_bit_reloc_info_ * kDoubleSize;
|
| }
|
|
|
| int size = size_up_to_marker + size_after_marker;
|
| @@ -3758,8 +3744,9 @@
|
| DCHECK((first_const_pool_32_use_ >= 0) || (first_const_pool_64_use_ >= 0));
|
| bool need_emit = false;
|
| if (has_fp_values) {
|
| - int dist64 = pc_offset() + size -
|
| - num_pending_32_bit_constants_ * kPointerSize -
|
| + int dist64 = pc_offset() +
|
| + size -
|
| + num_pending_32_bit_reloc_info_ * kPointerSize -
|
| first_const_pool_64_use_;
|
| if ((dist64 >= kMaxDistToFPPool - kCheckPoolInterval) ||
|
| (!require_jump && (dist64 >= kMaxDistToFPPool / 2))) {
|
| @@ -3801,52 +3788,60 @@
|
|
|
| // Emit 64-bit constant pool entries first: their range is smaller than
|
| // 32-bit entries.
|
| - for (int i = 0; i < num_pending_64_bit_constants_; i++) {
|
| - ConstantPoolEntry& entry = pending_64_bit_constants_[i];
|
| + for (int i = 0; i < num_pending_64_bit_reloc_info_; i++) {
|
| + RelocInfo& rinfo = pending_64_bit_reloc_info_[i];
|
|
|
| DCHECK(!((uintptr_t)pc_ & 0x7)); // Check 64-bit alignment.
|
|
|
| - Instr instr = instr_at(entry.position());
|
| + Instr instr = instr_at(rinfo.pc());
|
| // Instruction to patch must be 'vldr rd, [pc, #offset]' with offset == 0.
|
| DCHECK((IsVldrDPcImmediateOffset(instr) &&
|
| GetVldrDRegisterImmediateOffset(instr) == 0));
|
|
|
| - int delta = pc_offset() - entry.position() - kPcLoadDelta;
|
| + int delta = pc_ - rinfo.pc() - kPcLoadDelta;
|
| DCHECK(is_uint10(delta));
|
|
|
| bool found = false;
|
| - uint64_t value = entry.value64();
|
| + uint64_t value = rinfo.raw_data64();
|
| for (int j = 0; j < i; j++) {
|
| - ConstantPoolEntry& entry2 = pending_64_bit_constants_[j];
|
| - if (value == entry2.value64()) {
|
| + RelocInfo& rinfo2 = pending_64_bit_reloc_info_[j];
|
| + if (value == rinfo2.raw_data64()) {
|
| found = true;
|
| - Instr instr2 = instr_at(entry2.position());
|
| + DCHECK(rinfo2.rmode() == RelocInfo::NONE64);
|
| + Instr instr2 = instr_at(rinfo2.pc());
|
| DCHECK(IsVldrDPcImmediateOffset(instr2));
|
| delta = GetVldrDRegisterImmediateOffset(instr2);
|
| - delta += entry2.position() - entry.position();
|
| + delta += rinfo2.pc() - rinfo.pc();
|
| break;
|
| }
|
| }
|
|
|
| - instr_at_put(entry.position(),
|
| - SetVldrDRegisterImmediateOffset(instr, delta));
|
| + instr_at_put(rinfo.pc(), SetVldrDRegisterImmediateOffset(instr, delta));
|
|
|
| if (!found) {
|
| - dq(entry.value64());
|
| + uint64_t uint_data = rinfo.raw_data64();
|
| + emit(uint_data & 0xFFFFFFFF);
|
| + emit(uint_data >> 32);
|
| }
|
| }
|
|
|
| // Emit 32-bit constant pool entries.
|
| - for (int i = 0; i < num_pending_32_bit_constants_; i++) {
|
| - ConstantPoolEntry& entry = pending_32_bit_constants_[i];
|
| - Instr instr = instr_at(entry.position());
|
| + for (int i = 0; i < num_pending_32_bit_reloc_info_; i++) {
|
| + RelocInfo& rinfo = pending_32_bit_reloc_info_[i];
|
| + DCHECK(rinfo.rmode() != RelocInfo::COMMENT &&
|
| + rinfo.rmode() != RelocInfo::POSITION &&
|
| + rinfo.rmode() != RelocInfo::STATEMENT_POSITION &&
|
| + rinfo.rmode() != RelocInfo::CONST_POOL &&
|
| + rinfo.rmode() != RelocInfo::NONE64);
|
| +
|
| + Instr instr = instr_at(rinfo.pc());
|
|
|
| // 64-bit loads shouldn't get here.
|
| DCHECK(!IsVldrDPcImmediateOffset(instr));
|
|
|
| if (IsLdrPcImmediateOffset(instr) &&
|
| GetLdrRegisterImmediateOffset(instr) == 0) {
|
| - int delta = pc_offset() - entry.position() - kPcLoadDelta;
|
| + int delta = pc_ - rinfo.pc() - kPcLoadDelta;
|
| DCHECK(is_uint12(delta));
|
| // 0 is the smallest delta:
|
| // ldr rd, [pc, #0]
|
| @@ -3854,15 +3849,16 @@
|
| // data
|
|
|
| bool found = false;
|
| - if (entry.sharing_ok()) {
|
| + if (!serializer_enabled() && rinfo.rmode() >= RelocInfo::CELL) {
|
| for (int j = 0; j < i; j++) {
|
| - ConstantPoolEntry& entry2 = pending_32_bit_constants_[j];
|
| -
|
| - if (entry2.value() == entry.value()) {
|
| - Instr instr2 = instr_at(entry2.position());
|
| + RelocInfo& rinfo2 = pending_32_bit_reloc_info_[j];
|
| +
|
| + if ((rinfo2.data() == rinfo.data()) &&
|
| + (rinfo2.rmode() == rinfo.rmode())) {
|
| + Instr instr2 = instr_at(rinfo2.pc());
|
| if (IsLdrPcImmediateOffset(instr2)) {
|
| delta = GetLdrRegisterImmediateOffset(instr2);
|
| - delta += entry2.position() - entry.position();
|
| + delta += rinfo2.pc() - rinfo.pc();
|
| found = true;
|
| break;
|
| }
|
| @@ -3870,19 +3866,18 @@
|
| }
|
| }
|
|
|
| - instr_at_put(entry.position(),
|
| - SetLdrRegisterImmediateOffset(instr, delta));
|
| + instr_at_put(rinfo.pc(), SetLdrRegisterImmediateOffset(instr, delta));
|
|
|
| if (!found) {
|
| - emit(entry.value());
|
| + emit(rinfo.data());
|
| }
|
| } else {
|
| DCHECK(IsMovW(instr));
|
| }
|
| }
|
|
|
| - num_pending_32_bit_constants_ = 0;
|
| - num_pending_64_bit_constants_ = 0;
|
| + num_pending_32_bit_reloc_info_ = 0;
|
| + num_pending_64_bit_reloc_info_ = 0;
|
| first_const_pool_32_use_ = -1;
|
| first_const_pool_64_use_ = -1;
|
|
|
| @@ -3899,56 +3894,225 @@
|
| }
|
|
|
|
|
| -void Assembler::PatchConstantPoolAccessInstruction(
|
| - int pc_offset, int offset, ConstantPoolEntry::Access access,
|
| - ConstantPoolEntry::Type type) {
|
| - DCHECK(FLAG_enable_embedded_constant_pool);
|
| - Address pc = buffer_ + pc_offset;
|
| -
|
| - // Patch vldr/ldr instruction with correct offset.
|
| - Instr instr = instr_at(pc);
|
| - if (access == ConstantPoolEntry::OVERFLOWED) {
|
| - if (CpuFeatures::IsSupported(ARMv7)) {
|
| - // Instructions to patch must be 'movw rd, [#0]' and 'movt rd, [#0].
|
| - Instr next_instr = instr_at(pc + kInstrSize);
|
| - DCHECK((IsMovW(instr) && Instruction::ImmedMovwMovtValue(instr) == 0));
|
| - DCHECK((IsMovT(next_instr) &&
|
| - Instruction::ImmedMovwMovtValue(next_instr) == 0));
|
| - instr_at_put(pc, PatchMovwImmediate(instr, offset & 0xffff));
|
| - instr_at_put(pc + kInstrSize,
|
| - PatchMovwImmediate(next_instr, offset >> 16));
|
| +Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) {
|
| + if (!FLAG_enable_ool_constant_pool) {
|
| + return isolate->factory()->empty_constant_pool_array();
|
| + }
|
| + return constant_pool_builder_.New(isolate);
|
| +}
|
| +
|
| +
|
| +void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) {
|
| + constant_pool_builder_.Populate(this, constant_pool);
|
| +}
|
| +
|
| +
|
| +ConstantPoolBuilder::ConstantPoolBuilder()
|
| + : entries_(), current_section_(ConstantPoolArray::SMALL_SECTION) {}
|
| +
|
| +
|
| +bool ConstantPoolBuilder::IsEmpty() {
|
| + return entries_.size() == 0;
|
| +}
|
| +
|
| +
|
| +ConstantPoolArray::Type ConstantPoolBuilder::GetConstantPoolType(
|
| + RelocInfo::Mode rmode) {
|
| + if (rmode == RelocInfo::NONE64) {
|
| + return ConstantPoolArray::INT64;
|
| + } else if (!RelocInfo::IsGCRelocMode(rmode)) {
|
| + return ConstantPoolArray::INT32;
|
| + } else if (RelocInfo::IsCodeTarget(rmode)) {
|
| + return ConstantPoolArray::CODE_PTR;
|
| + } else {
|
| + DCHECK(RelocInfo::IsGCRelocMode(rmode) && !RelocInfo::IsCodeTarget(rmode));
|
| + return ConstantPoolArray::HEAP_PTR;
|
| + }
|
| +}
|
| +
|
| +
|
| +ConstantPoolArray::LayoutSection ConstantPoolBuilder::AddEntry(
|
| + Assembler* assm, const RelocInfo& rinfo) {
|
| + RelocInfo::Mode rmode = rinfo.rmode();
|
| + DCHECK(rmode != RelocInfo::COMMENT &&
|
| + rmode != RelocInfo::POSITION &&
|
| + rmode != RelocInfo::STATEMENT_POSITION &&
|
| + rmode != RelocInfo::CONST_POOL);
|
| +
|
| + // Try to merge entries which won't be patched.
|
| + int merged_index = -1;
|
| + ConstantPoolArray::LayoutSection entry_section = current_section_;
|
| + if (RelocInfo::IsNone(rmode) ||
|
| + (!assm->serializer_enabled() && (rmode >= RelocInfo::CELL))) {
|
| + size_t i;
|
| + std::vector<ConstantPoolEntry>::const_iterator it;
|
| + for (it = entries_.begin(), i = 0; it != entries_.end(); it++, i++) {
|
| + if (RelocInfo::IsEqual(rinfo, it->rinfo_)) {
|
| + // Merge with found entry.
|
| + merged_index = i;
|
| + entry_section = entries_[i].section_;
|
| + break;
|
| + }
|
| + }
|
| + }
|
| + DCHECK(entry_section <= current_section_);
|
| + entries_.push_back(ConstantPoolEntry(rinfo, entry_section, merged_index));
|
| +
|
| + if (merged_index == -1) {
|
| + // Not merged, so update the appropriate count.
|
| + number_of_entries_[entry_section].increment(GetConstantPoolType(rmode));
|
| + }
|
| +
|
| + // Check if we still have room for another entry in the small section
|
| + // given Arm's ldr and vldr immediate offset range.
|
| + if (current_section_ == ConstantPoolArray::SMALL_SECTION &&
|
| + !(is_uint12(ConstantPoolArray::SizeFor(*small_entries())) &&
|
| + is_uint10(ConstantPoolArray::MaxInt64Offset(
|
| + small_entries()->count_of(ConstantPoolArray::INT64))))) {
|
| + current_section_ = ConstantPoolArray::EXTENDED_SECTION;
|
| + }
|
| + return entry_section;
|
| +}
|
| +
|
| +
|
| +void ConstantPoolBuilder::Relocate(int pc_delta) {
|
| + for (std::vector<ConstantPoolEntry>::iterator entry = entries_.begin();
|
| + entry != entries_.end(); entry++) {
|
| + DCHECK(entry->rinfo_.rmode() != RelocInfo::JS_RETURN);
|
| + entry->rinfo_.set_pc(entry->rinfo_.pc() + pc_delta);
|
| + }
|
| +}
|
| +
|
| +
|
| +Handle<ConstantPoolArray> ConstantPoolBuilder::New(Isolate* isolate) {
|
| + if (IsEmpty()) {
|
| + return isolate->factory()->empty_constant_pool_array();
|
| + } else if (extended_entries()->is_empty()) {
|
| + return isolate->factory()->NewConstantPoolArray(*small_entries());
|
| + } else {
|
| + DCHECK(current_section_ == ConstantPoolArray::EXTENDED_SECTION);
|
| + return isolate->factory()->NewExtendedConstantPoolArray(
|
| + *small_entries(), *extended_entries());
|
| + }
|
| +}
|
| +
|
| +
|
| +void ConstantPoolBuilder::Populate(Assembler* assm,
|
| + ConstantPoolArray* constant_pool) {
|
| + DCHECK_EQ(extended_entries()->is_empty(),
|
| + !constant_pool->is_extended_layout());
|
| + DCHECK(small_entries()->equals(ConstantPoolArray::NumberOfEntries(
|
| + constant_pool, ConstantPoolArray::SMALL_SECTION)));
|
| + if (constant_pool->is_extended_layout()) {
|
| + DCHECK(extended_entries()->equals(ConstantPoolArray::NumberOfEntries(
|
| + constant_pool, ConstantPoolArray::EXTENDED_SECTION)));
|
| + }
|
| +
|
| + // Set up initial offsets.
|
| + int offsets[ConstantPoolArray::NUMBER_OF_LAYOUT_SECTIONS]
|
| + [ConstantPoolArray::NUMBER_OF_TYPES];
|
| + for (int section = 0; section <= constant_pool->final_section(); section++) {
|
| + int section_start = (section == ConstantPoolArray::EXTENDED_SECTION)
|
| + ? small_entries()->total_count()
|
| + : 0;
|
| + for (int i = 0; i < ConstantPoolArray::NUMBER_OF_TYPES; i++) {
|
| + ConstantPoolArray::Type type = static_cast<ConstantPoolArray::Type>(i);
|
| + if (number_of_entries_[section].count_of(type) != 0) {
|
| + offsets[section][type] = constant_pool->OffsetOfElementAt(
|
| + number_of_entries_[section].base_of(type) + section_start);
|
| + }
|
| + }
|
| + }
|
| +
|
| + for (std::vector<ConstantPoolEntry>::iterator entry = entries_.begin();
|
| + entry != entries_.end(); entry++) {
|
| + RelocInfo rinfo = entry->rinfo_;
|
| + RelocInfo::Mode rmode = entry->rinfo_.rmode();
|
| + ConstantPoolArray::Type type = GetConstantPoolType(rmode);
|
| +
|
| + // Update constant pool if necessary and get the entry's offset.
|
| + int offset;
|
| + if (entry->merged_index_ == -1) {
|
| + offset = offsets[entry->section_][type];
|
| + offsets[entry->section_][type] += ConstantPoolArray::entry_size(type);
|
| + if (type == ConstantPoolArray::INT64) {
|
| + constant_pool->set_at_offset(offset, rinfo.data64());
|
| + } else if (type == ConstantPoolArray::INT32) {
|
| + constant_pool->set_at_offset(offset,
|
| + static_cast<int32_t>(rinfo.data()));
|
| + } else if (type == ConstantPoolArray::CODE_PTR) {
|
| + constant_pool->set_at_offset(offset,
|
| + reinterpret_cast<Address>(rinfo.data()));
|
| + } else {
|
| + DCHECK(type == ConstantPoolArray::HEAP_PTR);
|
| + constant_pool->set_at_offset(offset,
|
| + reinterpret_cast<Object*>(rinfo.data()));
|
| + }
|
| + offset -= kHeapObjectTag;
|
| + entry->merged_index_ = offset; // Stash offset for merged entries.
|
| } else {
|
| - // Instructions to patch must be 'mov rd, [#0]' and 'orr rd, rd, [#0].
|
| - Instr instr_2 = instr_at(pc + kInstrSize);
|
| - Instr instr_3 = instr_at(pc + 2 * kInstrSize);
|
| - Instr instr_4 = instr_at(pc + 3 * kInstrSize);
|
| - DCHECK((IsMovImmed(instr) && Instruction::Immed8Value(instr) == 0));
|
| - DCHECK((IsOrrImmed(instr_2) && Instruction::Immed8Value(instr_2) == 0) &&
|
| - GetRn(instr_2).is(GetRd(instr_2)));
|
| - DCHECK((IsOrrImmed(instr_3) && Instruction::Immed8Value(instr_3) == 0) &&
|
| - GetRn(instr_3).is(GetRd(instr_3)));
|
| - DCHECK((IsOrrImmed(instr_4) && Instruction::Immed8Value(instr_4) == 0) &&
|
| - GetRn(instr_4).is(GetRd(instr_4)));
|
| - instr_at_put(pc, PatchShiftImm(instr, (offset & kImm8Mask)));
|
| - instr_at_put(pc + kInstrSize,
|
| - PatchShiftImm(instr_2, (offset & (kImm8Mask << 8))));
|
| - instr_at_put(pc + 2 * kInstrSize,
|
| - PatchShiftImm(instr_3, (offset & (kImm8Mask << 16))));
|
| - instr_at_put(pc + 3 * kInstrSize,
|
| - PatchShiftImm(instr_4, (offset & (kImm8Mask << 24))));
|
| - }
|
| - } else if (type == ConstantPoolEntry::DOUBLE) {
|
| - // Instruction to patch must be 'vldr rd, [pp, #0]'.
|
| - DCHECK((IsVldrDPpImmediateOffset(instr) &&
|
| - GetVldrDRegisterImmediateOffset(instr) == 0));
|
| - DCHECK(is_uint10(offset));
|
| - instr_at_put(pc, SetVldrDRegisterImmediateOffset(instr, offset));
|
| - } else {
|
| - // Instruction to patch must be 'ldr rd, [pp, #0]'.
|
| - DCHECK((IsLdrPpImmediateOffset(instr) &&
|
| - GetLdrRegisterImmediateOffset(instr) == 0));
|
| - DCHECK(is_uint12(offset));
|
| - instr_at_put(pc, SetLdrRegisterImmediateOffset(instr, offset));
|
| + DCHECK(entry->merged_index_ < (entry - entries_.begin()));
|
| + offset = entries_[entry->merged_index_].merged_index_;
|
| + }
|
| +
|
| + // Patch vldr/ldr instruction with correct offset.
|
| + Instr instr = assm->instr_at(rinfo.pc());
|
| + if (entry->section_ == ConstantPoolArray::EXTENDED_SECTION) {
|
| + if (CpuFeatures::IsSupported(ARMv7)) {
|
| + // Instructions to patch must be 'movw rd, [#0]' and 'movt rd, [#0].
|
| + Instr next_instr = assm->instr_at(rinfo.pc() + Assembler::kInstrSize);
|
| + DCHECK((Assembler::IsMovW(instr) &&
|
| + Instruction::ImmedMovwMovtValue(instr) == 0));
|
| + DCHECK((Assembler::IsMovT(next_instr) &&
|
| + Instruction::ImmedMovwMovtValue(next_instr) == 0));
|
| + assm->instr_at_put(
|
| + rinfo.pc(), Assembler::PatchMovwImmediate(instr, offset & 0xffff));
|
| + assm->instr_at_put(
|
| + rinfo.pc() + Assembler::kInstrSize,
|
| + Assembler::PatchMovwImmediate(next_instr, offset >> 16));
|
| + } else {
|
| + // Instructions to patch must be 'mov rd, [#0]' and 'orr rd, rd, [#0].
|
| + Instr instr_2 = assm->instr_at(rinfo.pc() + Assembler::kInstrSize);
|
| + Instr instr_3 = assm->instr_at(rinfo.pc() + 2 * Assembler::kInstrSize);
|
| + Instr instr_4 = assm->instr_at(rinfo.pc() + 3 * Assembler::kInstrSize);
|
| + DCHECK((Assembler::IsMovImmed(instr) &&
|
| + Instruction::Immed8Value(instr) == 0));
|
| + DCHECK((Assembler::IsOrrImmed(instr_2) &&
|
| + Instruction::Immed8Value(instr_2) == 0) &&
|
| + Assembler::GetRn(instr_2).is(Assembler::GetRd(instr_2)));
|
| + DCHECK((Assembler::IsOrrImmed(instr_3) &&
|
| + Instruction::Immed8Value(instr_3) == 0) &&
|
| + Assembler::GetRn(instr_3).is(Assembler::GetRd(instr_3)));
|
| + DCHECK((Assembler::IsOrrImmed(instr_4) &&
|
| + Instruction::Immed8Value(instr_4) == 0) &&
|
| + Assembler::GetRn(instr_4).is(Assembler::GetRd(instr_4)));
|
| + assm->instr_at_put(
|
| + rinfo.pc(), Assembler::PatchShiftImm(instr, (offset & kImm8Mask)));
|
| + assm->instr_at_put(
|
| + rinfo.pc() + Assembler::kInstrSize,
|
| + Assembler::PatchShiftImm(instr_2, (offset & (kImm8Mask << 8))));
|
| + assm->instr_at_put(
|
| + rinfo.pc() + 2 * Assembler::kInstrSize,
|
| + Assembler::PatchShiftImm(instr_3, (offset & (kImm8Mask << 16))));
|
| + assm->instr_at_put(
|
| + rinfo.pc() + 3 * Assembler::kInstrSize,
|
| + Assembler::PatchShiftImm(instr_4, (offset & (kImm8Mask << 24))));
|
| + }
|
| + } else if (type == ConstantPoolArray::INT64) {
|
| + // Instruction to patch must be 'vldr rd, [pp, #0]'.
|
| + DCHECK((Assembler::IsVldrDPpImmediateOffset(instr) &&
|
| + Assembler::GetVldrDRegisterImmediateOffset(instr) == 0));
|
| + DCHECK(is_uint10(offset));
|
| + assm->instr_at_put(rinfo.pc(), Assembler::SetVldrDRegisterImmediateOffset(
|
| + instr, offset));
|
| + } else {
|
| + // Instruction to patch must be 'ldr rd, [pp, #0]'.
|
| + DCHECK((Assembler::IsLdrPpImmediateOffset(instr) &&
|
| + Assembler::GetLdrRegisterImmediateOffset(instr) == 0));
|
| + DCHECK(is_uint12(offset));
|
| + assm->instr_at_put(
|
| + rinfo.pc(), Assembler::SetLdrRegisterImmediateOffset(instr, offset));
|
| + }
|
| }
|
| }
|
|
|
|
|