| Index: src/ppc/assembler-ppc-inl.h
|
| diff --git a/src/ppc/assembler-ppc-inl.h b/src/ppc/assembler-ppc-inl.h
|
| index d95c7ec5968a5e8fec471bdabed8f6dcf84d01d4..89a3d7ef7e0ec1e7cd032016028947ee4b10633f 100644
|
| --- a/src/ppc/assembler-ppc-inl.h
|
| +++ b/src/ppc/assembler-ppc-inl.h
|
| @@ -94,6 +94,13 @@ Address RelocInfo::target_address_address() {
|
| DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) ||
|
| rmode_ == EMBEDDED_OBJECT || rmode_ == EXTERNAL_REFERENCE);
|
|
|
| + if (FLAG_enable_embedded_constant_pool &&
|
| + Assembler::IsConstantPoolLoadStart(pc_)) {
|
| + // We return the PC for ool constant pool since this function is used by the
|
| + // serializer and expects the address to reside within the code object.
|
| + return reinterpret_cast<Address>(pc_);
|
| + }
|
| +
|
| // Read the address of the word containing the target_address in an
|
| // instruction stream.
|
| // The only architecture-independent user of this function is the serializer.
|
| @@ -108,6 +115,14 @@ Address RelocInfo::target_address_address() {
|
|
|
|
|
| Address RelocInfo::constant_pool_entry_address() {
|
| + if (FLAG_enable_embedded_constant_pool) {
|
| + Address constant_pool = host_->constant_pool();
|
| + DCHECK(constant_pool);
|
| + ConstantPoolEntry::Access access;
|
| + if (Assembler::IsConstantPoolLoadStart(pc_, &access))
|
| + return Assembler::target_constant_pool_address_at(
|
| + pc_, constant_pool, access, ConstantPoolEntry::INTPTR);
|
| + }
|
| UNREACHABLE();
|
| return NULL;
|
| }
|
| @@ -143,12 +158,28 @@ Address Assembler::target_address_from_return_address(Address pc) {
|
| // mtlr ip
|
| // blrl
|
| // @ return address
|
| - return pc - (kMovInstructions + 2) * kInstrSize;
|
| + int len;
|
| + ConstantPoolEntry::Access access;
|
| + if (FLAG_enable_embedded_constant_pool &&
|
| + IsConstantPoolLoadEnd(pc - 3 * kInstrSize, &access)) {
|
| + len = (access == ConstantPoolEntry::OVERFLOWED) ? 2 : 1;
|
| + } else {
|
| + len = kMovInstructionsNoConstantPool;
|
| + }
|
| + return pc - (len + 2) * kInstrSize;
|
| }
|
|
|
|
|
| Address Assembler::return_address_from_call_start(Address pc) {
|
| - return pc + (kMovInstructions + 2) * kInstrSize;
|
| + int len;
|
| + ConstantPoolEntry::Access access;
|
| + if (FLAG_enable_embedded_constant_pool &&
|
| + IsConstantPoolLoadStart(pc, &access)) {
|
| + len = (access == ConstantPoolEntry::OVERFLOWED) ? 2 : 1;
|
| + } else {
|
| + len = kMovInstructionsNoConstantPool;
|
| + }
|
| + return pc + (len + 2) * kInstrSize;
|
| }
|
|
|
|
|
| @@ -226,8 +257,10 @@ void RelocInfo::set_target_cell(Cell* cell, WriteBarrierMode write_barrier_mode,
|
| }
|
|
|
|
|
| -static const int kNoCodeAgeInstructions = 6;
|
| -static const int kCodeAgingInstructions = Assembler::kMovInstructions + 3;
|
| +static const int kNoCodeAgeInstructions =
|
| + FLAG_enable_embedded_constant_pool ? 7 : 6;
|
| +static const int kCodeAgingInstructions =
|
| + Assembler::kMovInstructionsNoConstantPool + 3;
|
| static const int kNoCodeAgeSequenceInstructions =
|
| ((kNoCodeAgeInstructions >= kCodeAgingInstructions)
|
| ? kNoCodeAgeInstructions
|
| @@ -448,8 +481,14 @@ bool Operand::is_reg() const { return rm_.is_valid(); }
|
|
|
|
|
| // Fetch the 32bit value from the FIXED_SEQUENCE lis/ori
|
| -Address Assembler::target_address_at(Address pc,
|
| - ConstantPoolArray* constant_pool) {
|
| +Address Assembler::target_address_at(Address pc, Address constant_pool) {
|
| + if (FLAG_enable_embedded_constant_pool && constant_pool) {
|
| + ConstantPoolEntry::Access access;
|
| + if (IsConstantPoolLoadStart(pc, &access))
|
| + return Memory::Address_at(target_constant_pool_address_at(
|
| + pc, constant_pool, access, ConstantPoolEntry::INTPTR));
|
| + }
|
| +
|
| Instr instr1 = instr_at(pc);
|
| Instr instr2 = instr_at(pc + kInstrSize);
|
| // Interpret 2 instructions generated by lis/ori
|
| @@ -475,6 +514,124 @@ Address Assembler::target_address_at(Address pc,
|
| }
|
|
|
|
|
| +#if V8_TARGET_ARCH_PPC64
|
| +const int kLoadIntptrOpcode = LD;
|
| +#else
|
| +const int kLoadIntptrOpcode = LWZ;
|
| +#endif
|
| +
|
| +// Constant pool load sequence detection:
|
| +// 1) REGULAR access:
|
| +// load <dst>, kConstantPoolRegister + <offset>
|
| +//
|
| +// 2) OVERFLOWED access:
|
| +// addis <scratch>, kConstantPoolRegister, <offset_high>
|
| +// load <dst>, <scratch> + <offset_low>
|
| +bool Assembler::IsConstantPoolLoadStart(Address pc,
|
| + ConstantPoolEntry::Access* access) {
|
| + Instr instr = instr_at(pc);
|
| + int opcode = instr & kOpcodeMask;
|
| + if (!GetRA(instr).is(kConstantPoolRegister)) return false;
|
| + bool overflowed = (opcode == ADDIS);
|
| +#ifdef DEBUG
|
| + if (overflowed) {
|
| + opcode = instr_at(pc + kInstrSize) & kOpcodeMask;
|
| + }
|
| + DCHECK(opcode == kLoadIntptrOpcode || opcode == LFD);
|
| +#endif
|
| + if (access) {
|
| + *access = (overflowed ? ConstantPoolEntry::OVERFLOWED
|
| + : ConstantPoolEntry::REGULAR);
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +
|
| +bool Assembler::IsConstantPoolLoadEnd(Address pc,
|
| + ConstantPoolEntry::Access* access) {
|
| + Instr instr = instr_at(pc);
|
| + int opcode = instr & kOpcodeMask;
|
| + if (!(opcode == kLoadIntptrOpcode || opcode == LFD)) return false;
|
| + bool overflowed = !GetRA(instr).is(kConstantPoolRegister);
|
| +#ifdef DEBUG
|
| + if (overflowed) {
|
| + instr = instr_at(pc - kInstrSize);
|
| + opcode = instr & kOpcodeMask;
|
| + DCHECK((opcode == ADDIS) && GetRA(instr).is(kConstantPoolRegister));
|
| + }
|
| +#endif
|
| + if (access) {
|
| + *access = (overflowed ? ConstantPoolEntry::OVERFLOWED
|
| + : ConstantPoolEntry::REGULAR);
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +
|
| +int Assembler::GetConstantPoolOffset(Address pc,
|
| + ConstantPoolEntry::Access access,
|
| + ConstantPoolEntry::Type type) {
|
| + bool overflowed = (access == ConstantPoolEntry::OVERFLOWED);
|
| +#ifdef DEBUG
|
| + ConstantPoolEntry::Access access_check;
|
| + DCHECK(IsConstantPoolLoadStart(pc, &access_check));
|
| + DCHECK(access_check == access);
|
| +#endif
|
| + int offset;
|
| + if (overflowed) {
|
| + offset = (instr_at(pc) & kImm16Mask) << 16;
|
| + offset += SIGN_EXT_IMM16(instr_at(pc + kInstrSize) & kImm16Mask);
|
| + DCHECK(!is_int16(offset));
|
| + } else {
|
| + offset = SIGN_EXT_IMM16((instr_at(pc) & kImm16Mask));
|
| + }
|
| + return offset;
|
| +}
|
| +
|
| +
|
| +void Assembler::PatchConstantPoolAccessInstruction(
|
| + int pc_offset, int offset, ConstantPoolEntry::Access access,
|
| + ConstantPoolEntry::Type type) {
|
| + Address pc = buffer_ + pc_offset;
|
| + bool overflowed = (access == ConstantPoolEntry::OVERFLOWED);
|
| +#ifdef DEBUG
|
| + ConstantPoolEntry::Access access_check;
|
| + DCHECK(IsConstantPoolLoadStart(pc, &access_check));
|
| + DCHECK(access_check == access);
|
| + DCHECK(overflowed != is_int16(offset));
|
| +#endif
|
| + if (overflowed) {
|
| + int hi_word = static_cast<int>(offset >> 16);
|
| + int lo_word = static_cast<int>(offset & 0xffff);
|
| + if (lo_word & 0x8000) hi_word++;
|
| +
|
| + Instr instr1 = instr_at(pc);
|
| + Instr instr2 = instr_at(pc + kInstrSize);
|
| + instr1 &= ~kImm16Mask;
|
| + instr1 |= (hi_word & kImm16Mask);
|
| + instr2 &= ~kImm16Mask;
|
| + instr2 |= (lo_word & kImm16Mask);
|
| + instr_at_put(pc, instr1);
|
| + instr_at_put(pc + kInstrSize, instr2);
|
| + } else {
|
| + Instr instr = instr_at(pc);
|
| + instr &= ~kImm16Mask;
|
| + instr |= (offset & kImm16Mask);
|
| + instr_at_put(pc, instr);
|
| + }
|
| +}
|
| +
|
| +
|
| +Address Assembler::target_constant_pool_address_at(
|
| + Address pc, Address constant_pool, ConstantPoolEntry::Access access,
|
| + ConstantPoolEntry::Type type) {
|
| + Address addr = constant_pool;
|
| + DCHECK(addr);
|
| + addr += GetConstantPoolOffset(pc, access, type);
|
| + return addr;
|
| +}
|
| +
|
| +
|
| // This sets the branch destination (which gets loaded at the call address).
|
| // This is for calls and branches within generated code. The serializer
|
| // has already deserialized the mov instructions etc.
|
| @@ -497,10 +654,18 @@ void Assembler::deserialization_set_target_internal_reference_at(
|
|
|
|
|
| // This code assumes the FIXED_SEQUENCE of lis/ori
|
| -void Assembler::set_target_address_at(Address pc,
|
| - ConstantPoolArray* constant_pool,
|
| +void Assembler::set_target_address_at(Address pc, Address constant_pool,
|
| Address target,
|
| ICacheFlushMode icache_flush_mode) {
|
| + if (FLAG_enable_embedded_constant_pool && constant_pool) {
|
| + ConstantPoolEntry::Access access;
|
| + if (IsConstantPoolLoadStart(pc, &access)) {
|
| + Memory::Address_at(target_constant_pool_address_at(
|
| + pc, constant_pool, access, ConstantPoolEntry::INTPTR)) = target;
|
| + return;
|
| + }
|
| + }
|
| +
|
| Instr instr1 = instr_at(pc);
|
| Instr instr2 = instr_at(pc + kInstrSize);
|
| // Interpret 2 instructions generated by lis/ori
|
|
|