[turbofan/cleanup] Make code target vector available in all back-ends

The code target vector is used by backends whenever initial code
creation uses immediates that cannot hold a code pointer: An index into
the vector is used instead, and the vector contains the corresponding
code object. This CL makes the code target vector available on all
platforms.

Bug: v8:6666
Change-Id: I2026acd6a77a3465fe2285b84d47866c3b794855
Reviewed-on: https://chromium-review.googlesource.com/1118885
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54236}
This commit is contained in:
Sigurd Schneider 2018-07-05 10:37:18 +02:00 committed by Commit Bot
parent de100afbe0
commit 8e5269ba04
12 changed files with 80 additions and 92 deletions

View File

@ -549,11 +549,8 @@ Handle<Code> Assembler::code_target_object_handle_at(Address pc) {
Assembler::target_address_at(pc, 0 /* unused */)));
} else {
DCHECK(instr->IsBranchAndLink() || instr->IsUnconditionalBranch());
DCHECK_GE(instr->ImmPCOffset(), 0);
DCHECK_EQ(instr->ImmPCOffset() % kInstructionSize, 0);
DCHECK_LT(instr->ImmPCOffset() >> kInstructionSizeLog2,
code_targets_.size());
return code_targets_[instr->ImmPCOffset() >> kInstructionSizeLog2];
return GetCodeTarget(instr->ImmPCOffset() >> kInstructionSizeLog2);
}
}

View File

@ -578,7 +578,7 @@ void Assembler::Reset() {
memset(buffer_, 0, pc_ - buffer_);
#endif
pc_ = buffer_;
code_targets_.reserve(64);
ReserveCodeTargetSpace(64);
reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
constpool_.Clear();
next_constant_pool_check_ = 0;
@ -600,12 +600,9 @@ void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
request.code_stub()->set_isolate(isolate);
Instruction* instr = reinterpret_cast<Instruction*>(pc);
DCHECK(instr->IsBranchAndLink() || instr->IsUnconditionalBranch());
DCHECK_GE(instr->ImmPCOffset(), 0);
DCHECK_EQ(instr->ImmPCOffset() % kInstructionSize, 0);
DCHECK_LT(instr->ImmPCOffset() >> kInstructionSizeLog2,
code_targets_.size());
code_targets_[instr->ImmPCOffset() >> kInstructionSizeLog2] =
request.code_stub()->GetCode();
UpdateCodeTarget(instr->ImmPCOffset() >> kInstructionSizeLog2,
request.code_stub()->GetCode());
break;
}
}
@ -4793,18 +4790,6 @@ void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data,
}
}
int Assembler::GetCodeTargetIndex(Handle<Code> target) {
int current = static_cast<int>(code_targets_.size());
if (current > 0 && !target.is_null() &&
code_targets_.back().address() == target.address()) {
// Optimization if we keep jumping to the same code target.
return (current - 1);
} else {
code_targets_.push_back(target);
return current;
}
}
void Assembler::near_jump(int offset, RelocInfo::Mode rmode) {
if (!RelocInfo::IsNone(rmode)) RecordRelocInfo(rmode, offset, NO_POOL_ENTRY);
b(offset);
@ -4817,7 +4802,7 @@ void Assembler::near_call(int offset, RelocInfo::Mode rmode) {
void Assembler::near_call(HeapObjectRequest request) {
RequestHeapObject(request);
int index = GetCodeTargetIndex(Handle<Code>());
int index = AddCodeTarget(Handle<Code>());
RecordRelocInfo(RelocInfo::CODE_TARGET, index, NO_POOL_ENTRY);
bl(index);
}

View File

@ -970,10 +970,6 @@ class Assembler : public AssemblerBase {
Address pc, Address constant_pool, Address target,
ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
// Add 'target' to the code_targets_ vector, if necessary, and return the
// offset at which it is stored.
int GetCodeTargetIndex(Handle<Code> target);
// Returns the handle for the code object called at 'pc'.
// This might need to be temporarily encoded as an offset into code_targets_.
inline Handle<Code> code_target_object_handle_at(Address pc);
@ -3504,14 +3500,6 @@ class Assembler : public AssemblerBase {
// are already bound.
std::deque<int> internal_reference_positions_;
// Before we copy code into the code space, we cannot encode calls to code
// targets as we normally would, as the difference between the instruction's
// location in the temporary buffer and the call target is not guaranteed to
// fit in the offset field. We keep track of the code handles we encounter
// in calls in this vector, and encode the index of the code handle in the
// vector instead.
std::vector<Handle<Code>> code_targets_;
// Relocation info records are also used during code generation as temporary
// containers for constants and code target addresses until they are emitted
// to the constant pool. These pending relocation info records are temporarily

View File

@ -1955,7 +1955,7 @@ void TurboAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode,
}
}
if (CanUseNearCallOrJump(rmode)) {
JumpHelper(static_cast<int64_t>(GetCodeTargetIndex(code)), rmode, cond);
JumpHelper(static_cast<int64_t>(AddCodeTarget(code)), rmode, cond);
} else {
Jump(code.address(), rmode, cond);
}
@ -2028,7 +2028,7 @@ void TurboAssembler::Call(Handle<Code> code, RelocInfo::Mode rmode) {
}
}
if (CanUseNearCallOrJump(rmode)) {
near_call(GetCodeTargetIndex(code), rmode);
near_call(AddCodeTarget(code), rmode);
} else {
IndirectCall(code.address(), rmode);
}

View File

@ -910,5 +910,30 @@ void AssemblerBase::RequestHeapObject(HeapObjectRequest request) {
heap_object_requests_.push_front(request);
}
int AssemblerBase::AddCodeTarget(Handle<Code> target) {
int current = static_cast<int>(code_targets_.size());
if (current > 0 && !target.is_null() &&
code_targets_.back().address() == target.address()) {
// Optimization if we keep jumping to the same code target.
return current - 1;
} else {
code_targets_.push_back(target);
return current;
}
}
Handle<Code> AssemblerBase::GetCodeTarget(intptr_t code_target_index) const {
DCHECK_LE(0, code_target_index);
DCHECK_LT(code_target_index, code_targets_.size());
return code_targets_[code_target_index];
}
void AssemblerBase::UpdateCodeTarget(intptr_t code_target_index,
Handle<Code> code) {
DCHECK_LE(0, code_target_index);
DCHECK_LT(code_target_index, code_targets_.size());
code_targets_[code_target_index] = code;
}
} // namespace internal
} // namespace v8

View File

@ -229,6 +229,17 @@ class AssemblerBase : public Malloced {
static const char* GetSpecialRegisterName(int code) { return "UNKNOWN"; }
protected:
// Add 'target' to the {code_targets_} vector, if necessary, and return the
// offset at which it is stored.
int AddCodeTarget(Handle<Code> target);
Handle<Code> GetCodeTarget(intptr_t code_target_index) const;
// Update to the code target at {code_target_index} to {target}.
void UpdateCodeTarget(intptr_t code_target_index, Handle<Code> target);
// Reserves space in the code target vector.
void ReserveCodeTargetSpace(size_t num_of_code_targets) {
code_targets_.reserve(num_of_code_targets);
}
// The buffer into which code and relocation info are generated. It could
// either be owned by the assembler or be provided externally.
byte* buffer_;
@ -256,6 +267,14 @@ class AssemblerBase : public Malloced {
void RequestHeapObject(HeapObjectRequest request);
private:
// Before we copy code into the code space, we sometimes cannot encode
// call/jump code targets as we normally would, as the difference between the
// instruction's location in the temporary buffer and the call target is not
// guaranteed to fit in the instruction's offset field. We keep track of the
// code handles we encounter in calls in this vector, and encode the index of
// the code handle in the vector instead.
std::vector<Handle<Code>> code_targets_;
const Options options_;
uint64_t enabled_cpu_features_;
bool emit_debug_code_;

View File

@ -137,7 +137,7 @@ Handle<Object> Assembler::code_target_object_handle_at(Address pc) {
SixByteInstr instr =
Instruction::InstructionBits(reinterpret_cast<const byte*>(pc));
int index = instr & 0xFFFFFFFF;
return code_targets_[index];
return GetCodeTarget(index);
}
HeapObject* RelocInfo::target_object() {
@ -237,23 +237,6 @@ void RelocInfo::Visit(ObjectVisitor* visitor) {
// Operand constructors
Operand::Operand(Register rm) : rm_(rm), rmode_(RelocInfo::NONE) {}
int32_t Assembler::emit_code_target(Handle<Code> target,
RelocInfo::Mode rmode) {
DCHECK(RelocInfo::IsCodeTarget(rmode));
RecordRelocInfo(rmode);
size_t current = code_targets_.size();
if (current > 0 && !target.is_null() &&
code_targets_.back().address() == target.address()) {
// Optimization if we keep jumping to the same code target.
current--;
} else {
code_targets_.push_back(target);
}
return current;
}
// Fetch the 32bit value from the FIXED_SEQUENCE IIHF / IILF
Address Assembler::target_address_at(Address pc, Address constant_pool) {
// S390 Instruction!

View File

@ -338,7 +338,7 @@ void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
SixByteInstr instr =
Instruction::InstructionBits(reinterpret_cast<const byte*>(pc));
int index = instr & 0xFFFFFFFF;
code_targets_[index] = request.code_stub()->GetCode();
UpdateCodeTarget(index, request.code_stub()->GetCode());
break;
}
}
@ -350,8 +350,7 @@ void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
Assembler::Assembler(const Options& options, void* buffer, int buffer_size)
: AssemblerBase(options, buffer, buffer_size) {
reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
code_targets_.reserve(100);
ReserveCodeTargetSpace(100);
last_bound_pos_ = 0;
relocations_.reserve(128);
}
@ -667,25 +666,29 @@ void Assembler::EnsureSpaceFor(int space_needed) {
}
void Assembler::call(Handle<Code> target, RelocInfo::Mode rmode) {
DCHECK(RelocInfo::IsCodeTarget(rmode));
EnsureSpace ensure_space(this);
int32_t target_index = emit_code_target(target, rmode);
RecordRelocInfo(rmode);
int32_t target_index = AddCodeTarget(target);
brasl(r14, Operand(target_index));
}
void Assembler::call(CodeStub* stub) {
EnsureSpace ensure_space(this);
RequestHeapObject(HeapObjectRequest(stub));
int32_t target_index =
emit_code_target(Handle<Code>(), RelocInfo::CODE_TARGET);
RecordRelocInfo(RelocInfo::CODE_TARGET);
int32_t target_index = AddCodeTarget(Handle<Code>());
brasl(r14, Operand(target_index));
}
void Assembler::jump(Handle<Code> target, RelocInfo::Mode rmode,
Condition cond) {
DCHECK(RelocInfo::IsCodeTarget(rmode));
EnsureSpace ensure_space(this);
int32_t target_index = emit_code_target(target, rmode);
RecordRelocInfo(rmode);
int32_t target_index = AddCodeTarget(target);
brcl(cond, Operand(target_index));
}

View File

@ -1558,9 +1558,6 @@ inline void ss_a_format(Opcode op, int f1, int f2, int f3, int f4, int f5) {
inline void TrackBranch();
inline void UntrackBranch();
inline int32_t emit_code_target(
Handle<Code> target, RelocInfo::Mode rmode);
// Helper to emit the binary encoding of a 2 byte instruction
void emit2bytes(uint16_t x) {
CheckBuffer();
@ -1625,8 +1622,6 @@ inline void ss_a_format(Opcode op, int f1, int f2, int f3, int f4, int f5) {
friend class RegExpMacroAssemblerS390;
friend class RelocInfo;
friend class EnsureSpace;
std::vector<Handle<Code>> code_targets_;
};
class EnsureSpace BASE_EMBEDDED {

View File

@ -48,21 +48,6 @@ void Assembler::emitw(uint16_t x) {
pc_ += sizeof(uint16_t);
}
void Assembler::emit_code_target(Handle<Code> target, RelocInfo::Mode rmode) {
DCHECK(RelocInfo::IsCodeTarget(rmode));
RecordRelocInfo(rmode);
int current = static_cast<int>(code_targets_.size());
if (current > 0 && !target.is_null() &&
code_targets_.back().address() == target.address()) {
// Optimization if we keep jumping to the same code target.
emitl(current - 1);
} else {
code_targets_.push_back(target);
emitl(current);
}
}
void Assembler::emit_runtime_entry(Address entry, RelocInfo::Mode rmode) {
DCHECK(RelocInfo::IsRuntimeEntry(rmode));
RecordRelocInfo(rmode);
@ -278,7 +263,7 @@ int Assembler::deserialization_special_target_size(
}
Handle<Code> Assembler::code_target_object_handle_at(Address pc) {
return code_targets_[Memory::int32_at(pc)];
return GetCodeTarget(Memory::int32_at(pc));
}
Address Assembler::runtime_entry_at(Address pc) {

View File

@ -346,7 +346,7 @@ void Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) {
}
case HeapObjectRequest::kCodeStub: {
request.code_stub()->set_isolate(isolate);
code_targets_[Memory::int32_at(pc)] = request.code_stub()->GetCode();
UpdateCodeTarget(Memory::int32_at(pc), request.code_stub()->GetCode());
break;
}
}
@ -367,7 +367,7 @@ Assembler::Assembler(const Options& options, void* buffer, int buffer_size)
}
#endif
code_targets_.reserve(100);
ReserveCodeTargetSpace(100);
reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
}
@ -981,14 +981,19 @@ void Assembler::call(CodeStub* stub) {
// 1110 1000 #32-bit disp.
emit(0xE8);
RequestHeapObject(HeapObjectRequest(stub));
emit_code_target(Handle<Code>(), RelocInfo::CODE_TARGET);
RecordRelocInfo(RelocInfo::CODE_TARGET);
int code_target_index = AddCodeTarget(Handle<Code>());
emitl(code_target_index);
}
void Assembler::call(Handle<Code> target, RelocInfo::Mode rmode) {
DCHECK(RelocInfo::IsCodeTarget(rmode));
EnsureSpace ensure_space(this);
// 1110 1000 #32-bit disp.
emit(0xE8);
emit_code_target(target, rmode);
RecordRelocInfo(rmode);
int code_target_index = AddCodeTarget(target);
emitl(code_target_index);
}
void Assembler::near_call(Address addr, RelocInfo::Mode rmode) {
@ -1430,7 +1435,10 @@ void Assembler::j(Condition cc,
// 0000 1111 1000 tttn #32-bit disp.
emit(0x0F);
emit(0x80 | cc);
emit_code_target(target, rmode);
DCHECK(RelocInfo::IsCodeTarget(rmode));
RecordRelocInfo(rmode);
int code_target_index = AddCodeTarget(target);
emitl(code_target_index);
}
@ -1491,10 +1499,13 @@ void Assembler::jmp(Label* L, Label::Distance distance) {
void Assembler::jmp(Handle<Code> target, RelocInfo::Mode rmode) {
DCHECK(RelocInfo::IsCodeTarget(rmode));
EnsureSpace ensure_space(this);
// 1110 1001 #32-bit disp.
emit(0xE9);
emit_code_target(target, rmode);
RecordRelocInfo(rmode);
int code_target_index = AddCodeTarget(target);
emitl(code_target_index);
}

View File

@ -1935,7 +1935,6 @@ class Assembler : public AssemblerBase {
inline void emitp(Address x, RelocInfo::Mode rmode);
inline void emitq(uint64_t x);
inline void emitw(uint16_t x);
inline void emit_code_target(Handle<Code> target, RelocInfo::Mode rmode);
inline void emit_runtime_entry(Address entry, RelocInfo::Mode rmode);
inline void emit(Immediate x);
@ -2371,8 +2370,6 @@ class Assembler : public AssemblerBase {
// are already bound.
std::deque<int> internal_reference_positions_;
std::vector<Handle<Code>> code_targets_;
// Variables for this instance of assembler
int farjmp_num_ = 0;
std::deque<int> farjmp_positions_;