[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:
parent
de100afbe0
commit
8e5269ba04
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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_;
|
||||
|
@ -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!
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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_;
|
||||
|
Loading…
Reference in New Issue
Block a user