PPC/s390: enable --perf-prof on PPC and S390
Change-Id: I88adc527fea64c8ab6e9b32cfd8d40927e78da9a Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1874087 Reviewed-by: Jakob Gruber <jgruber@chromium.org> Reviewed-by: Junliang Yan <jyan@ca.ibm.com> Commit-Queue: Junliang Yan <jyan@ca.ibm.com> Cr-Commit-Position: refs/heads/master@{#64931}
This commit is contained in:
parent
3ee5dbc0ca
commit
b6ef2517aa
6
BUILD.gn
6
BUILD.gn
@ -3160,9 +3160,12 @@ v8_source_set("v8_base_without_compiler") {
|
||||
"src/compiler/backend/ppc/instruction-codes-ppc.h",
|
||||
"src/compiler/backend/ppc/instruction-scheduler-ppc.cc",
|
||||
"src/compiler/backend/ppc/instruction-selector-ppc.cc",
|
||||
"src/compiler/backend/ppc/unwinding-info-writer-ppc.cc",
|
||||
"src/compiler/backend/ppc/unwinding-info-writer-ppc.h",
|
||||
"src/debug/ppc/debug-ppc.cc",
|
||||
"src/deoptimizer/ppc/deoptimizer-ppc.cc",
|
||||
"src/diagnostics/ppc/disasm-ppc.cc",
|
||||
"src/diagnostics/ppc/eh-frame-ppc.cc",
|
||||
"src/execution/ppc/frame-constants-ppc.cc",
|
||||
"src/execution/ppc/frame-constants-ppc.h",
|
||||
"src/execution/ppc/simulator-ppc.cc",
|
||||
@ -3187,9 +3190,12 @@ v8_source_set("v8_base_without_compiler") {
|
||||
"src/compiler/backend/s390/instruction-codes-s390.h",
|
||||
"src/compiler/backend/s390/instruction-scheduler-s390.cc",
|
||||
"src/compiler/backend/s390/instruction-selector-s390.cc",
|
||||
"src/compiler/backend/s390/unwinding-info-writer-s390.cc",
|
||||
"src/compiler/backend/s390/unwinding-info-writer-s390.h",
|
||||
"src/debug/s390/debug-s390.cc",
|
||||
"src/deoptimizer/s390/deoptimizer-s390.cc",
|
||||
"src/diagnostics/s390/disasm-s390.cc",
|
||||
"src/diagnostics/s390/eh-frame-s390.cc",
|
||||
"src/execution/s390/frame-constants-s390.cc",
|
||||
"src/execution/s390/frame-constants-s390.h",
|
||||
"src/execution/s390/simulator-s390.cc",
|
||||
|
@ -2992,4 +2992,9 @@ class DoubleRegisters {
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
static constexpr int kR0DwarfCode = 0;
|
||||
static constexpr int kFpDwarfCode = 31; // frame-pointer
|
||||
static constexpr int kLrDwarfCode = 65; // return-address(lr)
|
||||
static constexpr int kSpDwarfCode = 1; // stack-pointer (sp)
|
||||
|
||||
#endif // V8_CODEGEN_PPC_CONSTANTS_PPC_H_
|
||||
|
@ -129,7 +129,8 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
|
||||
public:
|
||||
OutOfLineRecordWrite(CodeGenerator* gen, Register object, Register offset,
|
||||
Register value, Register scratch0, Register scratch1,
|
||||
RecordWriteMode mode, StubCallMode stub_mode)
|
||||
RecordWriteMode mode, StubCallMode stub_mode,
|
||||
UnwindingInfoWriter* unwinding_info_writer)
|
||||
: OutOfLineCode(gen),
|
||||
object_(object),
|
||||
offset_(offset),
|
||||
@ -140,11 +141,13 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
|
||||
mode_(mode),
|
||||
stub_mode_(stub_mode),
|
||||
must_save_lr_(!gen->frame_access_state()->has_frame()),
|
||||
unwinding_info_writer_(unwinding_info_writer),
|
||||
zone_(gen->zone()) {}
|
||||
|
||||
OutOfLineRecordWrite(CodeGenerator* gen, Register object, int32_t offset,
|
||||
Register value, Register scratch0, Register scratch1,
|
||||
RecordWriteMode mode, StubCallMode stub_mode)
|
||||
RecordWriteMode mode, StubCallMode stub_mode,
|
||||
UnwindingInfoWriter* unwinding_info_writer)
|
||||
: OutOfLineCode(gen),
|
||||
object_(object),
|
||||
offset_(no_reg),
|
||||
@ -155,6 +158,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
|
||||
mode_(mode),
|
||||
stub_mode_(stub_mode),
|
||||
must_save_lr_(!gen->frame_access_state()->has_frame()),
|
||||
unwinding_info_writer_(unwinding_info_writer),
|
||||
zone_(gen->zone()) {}
|
||||
|
||||
void Generate() final {
|
||||
@ -180,6 +184,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
|
||||
// We need to save and restore lr if the frame was elided.
|
||||
__ mflr(scratch0_);
|
||||
__ Push(scratch0_);
|
||||
unwinding_info_writer_->MarkLinkRegisterOnTopOfStack(__ pc_offset());
|
||||
}
|
||||
if (mode_ == RecordWriteMode::kValueIsEphemeronKey) {
|
||||
__ CallEphemeronKeyBarrier(object_, scratch1_, save_fp_mode);
|
||||
@ -194,6 +199,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
|
||||
// We need to save and restore lr if the frame was elided.
|
||||
__ Pop(scratch0_);
|
||||
__ mtlr(scratch0_);
|
||||
unwinding_info_writer_->MarkPopLinkRegisterFromTopOfStack(__ pc_offset());
|
||||
}
|
||||
}
|
||||
|
||||
@ -207,6 +213,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
|
||||
RecordWriteMode const mode_;
|
||||
StubCallMode stub_mode_;
|
||||
bool must_save_lr_;
|
||||
UnwindingInfoWriter* const unwinding_info_writer_;
|
||||
Zone* zone_;
|
||||
};
|
||||
|
||||
@ -675,6 +682,7 @@ void EmitWordLoadPoisoningIfNeeded(CodeGenerator* codegen, Instruction* instr,
|
||||
|
||||
void CodeGenerator::AssembleDeconstructFrame() {
|
||||
__ LeaveFrame(StackFrame::MANUAL);
|
||||
unwinding_info_writer_.MarkFrameDeconstructed(__ pc_offset());
|
||||
}
|
||||
|
||||
void CodeGenerator::AssemblePrepareTailCall() {
|
||||
@ -1182,16 +1190,16 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
AddressingModeField::decode(instr->opcode());
|
||||
if (addressing_mode == kMode_MRI) {
|
||||
int32_t offset = i.InputInt32(1);
|
||||
ool = new (zone())
|
||||
OutOfLineRecordWrite(this, object, offset, value, scratch0,
|
||||
scratch1, mode, DetermineStubCallMode());
|
||||
ool = new (zone()) OutOfLineRecordWrite(
|
||||
this, object, offset, value, scratch0, scratch1, mode,
|
||||
DetermineStubCallMode(), &unwinding_info_writer_);
|
||||
__ StoreP(value, MemOperand(object, offset));
|
||||
} else {
|
||||
DCHECK_EQ(kMode_MRR, addressing_mode);
|
||||
Register offset(i.InputRegister(1));
|
||||
ool = new (zone())
|
||||
OutOfLineRecordWrite(this, object, offset, value, scratch0,
|
||||
scratch1, mode, DetermineStubCallMode());
|
||||
ool = new (zone()) OutOfLineRecordWrite(
|
||||
this, object, offset, value, scratch0, scratch1, mode,
|
||||
DetermineStubCallMode(), &unwinding_info_writer_);
|
||||
__ StorePX(value, MemOperand(object, offset));
|
||||
}
|
||||
__ CheckPageFlag(object, scratch0,
|
||||
@ -2407,6 +2415,7 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
}
|
||||
}
|
||||
}
|
||||
unwinding_info_writer_.MarkFrameConstructed(__ pc_offset());
|
||||
}
|
||||
|
||||
int required_slots =
|
||||
@ -2517,6 +2526,7 @@ void CodeGenerator::AssembleReturn(InstructionOperand* pop) {
|
||||
__ MultiPopDoubles(double_saves);
|
||||
}
|
||||
PPCOperandConverter g(this, nullptr);
|
||||
unwinding_info_writer_.MarkBlockWillExit();
|
||||
|
||||
if (call_descriptor->IsCFunctionCall()) {
|
||||
AssembleDeconstructFrame();
|
||||
|
105
src/compiler/backend/ppc/unwinding-info-writer-ppc.cc
Normal file
105
src/compiler/backend/ppc/unwinding-info-writer-ppc.cc
Normal file
@ -0,0 +1,105 @@
|
||||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/compiler/backend/ppc/unwinding-info-writer-ppc.h"
|
||||
#include "src/compiler/backend/instruction.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
void UnwindingInfoWriter::BeginInstructionBlock(int pc_offset,
|
||||
const InstructionBlock* block) {
|
||||
if (!enabled()) return;
|
||||
|
||||
block_will_exit_ = false;
|
||||
|
||||
DCHECK_LT(block->rpo_number().ToInt(),
|
||||
static_cast<int>(block_initial_states_.size()));
|
||||
const BlockInitialState* initial_state =
|
||||
block_initial_states_[block->rpo_number().ToInt()];
|
||||
if (!initial_state) return;
|
||||
if (initial_state->saved_lr_ != saved_lr_) {
|
||||
eh_frame_writer_.AdvanceLocation(pc_offset);
|
||||
if (initial_state->saved_lr_) {
|
||||
eh_frame_writer_.RecordRegisterSavedToStack(kLrDwarfCode,
|
||||
kSystemPointerSize);
|
||||
eh_frame_writer_.RecordRegisterSavedToStack(fp, 0);
|
||||
} else {
|
||||
eh_frame_writer_.RecordRegisterFollowsInitialRule(kLrDwarfCode);
|
||||
}
|
||||
saved_lr_ = initial_state->saved_lr_;
|
||||
}
|
||||
}
|
||||
|
||||
void UnwindingInfoWriter::EndInstructionBlock(const InstructionBlock* block) {
|
||||
if (!enabled() || block_will_exit_) return;
|
||||
|
||||
for (const RpoNumber& successor : block->successors()) {
|
||||
int successor_index = successor.ToInt();
|
||||
DCHECK_LT(successor_index, static_cast<int>(block_initial_states_.size()));
|
||||
const BlockInitialState* existing_state =
|
||||
block_initial_states_[successor_index];
|
||||
|
||||
// If we already had an entry for this BB, check that the values are the
|
||||
// same we are trying to insert.
|
||||
if (existing_state) {
|
||||
DCHECK_EQ(existing_state->saved_lr_, saved_lr_);
|
||||
} else {
|
||||
block_initial_states_[successor_index] =
|
||||
new (zone_) BlockInitialState(saved_lr_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UnwindingInfoWriter::MarkFrameConstructed(int at_pc) {
|
||||
if (!enabled()) return;
|
||||
|
||||
// Regardless of the type of frame constructed, the relevant part of the
|
||||
// layout is always the one in the diagram:
|
||||
//
|
||||
// | .... | higher addresses
|
||||
// +----------+ ^
|
||||
// | LR | | |
|
||||
// +----------+ | |
|
||||
// | saved FP | | |
|
||||
// +----------+ <-- FP v
|
||||
// | .... | stack growth
|
||||
//
|
||||
// The LR is pushed on the stack, and we can record this fact at the end of
|
||||
// the construction, since the LR itself is not modified in the process.
|
||||
eh_frame_writer_.AdvanceLocation(at_pc);
|
||||
eh_frame_writer_.RecordRegisterSavedToStack(kLrDwarfCode,
|
||||
kSystemPointerSize);
|
||||
eh_frame_writer_.RecordRegisterSavedToStack(fp, 0);
|
||||
saved_lr_ = true;
|
||||
}
|
||||
|
||||
void UnwindingInfoWriter::MarkFrameDeconstructed(int at_pc) {
|
||||
if (!enabled()) return;
|
||||
|
||||
// The lr is restored by the last operation in LeaveFrame().
|
||||
eh_frame_writer_.AdvanceLocation(at_pc);
|
||||
eh_frame_writer_.RecordRegisterFollowsInitialRule(kLrDwarfCode);
|
||||
saved_lr_ = false;
|
||||
}
|
||||
|
||||
void UnwindingInfoWriter::MarkLinkRegisterOnTopOfStack(int pc_offset) {
|
||||
if (!enabled()) return;
|
||||
|
||||
eh_frame_writer_.AdvanceLocation(pc_offset);
|
||||
eh_frame_writer_.SetBaseAddressRegisterAndOffset(sp, 0);
|
||||
eh_frame_writer_.RecordRegisterSavedToStack(r30, 0);
|
||||
}
|
||||
|
||||
void UnwindingInfoWriter::MarkPopLinkRegisterFromTopOfStack(int pc_offset) {
|
||||
if (!enabled()) return;
|
||||
|
||||
eh_frame_writer_.AdvanceLocation(pc_offset);
|
||||
eh_frame_writer_.SetBaseAddressRegisterAndOffset(fp, 0);
|
||||
eh_frame_writer_.RecordRegisterFollowsInitialRule(kLrDwarfCode);
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
73
src/compiler/backend/ppc/unwinding-info-writer-ppc.h
Normal file
73
src/compiler/backend/ppc/unwinding-info-writer-ppc.h
Normal file
@ -0,0 +1,73 @@
|
||||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_COMPILER_BACKEND_PPC_UNWINDING_INFO_WRITER_PPC_H_
|
||||
#define V8_COMPILER_BACKEND_PPC_UNWINDING_INFO_WRITER_PPC_H_
|
||||
|
||||
#include "src/diagnostics/eh-frame.h"
|
||||
#include "src/flags/flags.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
|
||||
class InstructionBlock;
|
||||
|
||||
class UnwindingInfoWriter {
|
||||
public:
|
||||
explicit UnwindingInfoWriter(Zone* zone)
|
||||
: zone_(zone),
|
||||
eh_frame_writer_(zone),
|
||||
saved_lr_(false),
|
||||
block_will_exit_(false),
|
||||
block_initial_states_(zone) {
|
||||
if (enabled()) eh_frame_writer_.Initialize();
|
||||
}
|
||||
|
||||
void SetNumberOfInstructionBlocks(int number) {
|
||||
if (enabled()) block_initial_states_.resize(number);
|
||||
}
|
||||
|
||||
void BeginInstructionBlock(int pc_offset, const InstructionBlock* block);
|
||||
void EndInstructionBlock(const InstructionBlock* block);
|
||||
|
||||
void MarkLinkRegisterOnTopOfStack(int pc_offset);
|
||||
void MarkPopLinkRegisterFromTopOfStack(int pc_offset);
|
||||
|
||||
void MarkFrameConstructed(int at_pc);
|
||||
void MarkFrameDeconstructed(int at_pc);
|
||||
|
||||
void MarkBlockWillExit() { block_will_exit_ = true; }
|
||||
|
||||
void Finish(int code_size) {
|
||||
if (enabled()) eh_frame_writer_.Finish(code_size);
|
||||
}
|
||||
|
||||
EhFrameWriter* eh_frame_writer() {
|
||||
return enabled() ? &eh_frame_writer_ : nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
bool enabled() const { return FLAG_perf_prof_unwinding_info; }
|
||||
|
||||
class BlockInitialState : public ZoneObject {
|
||||
public:
|
||||
explicit BlockInitialState(bool saved_lr) : saved_lr_(saved_lr) {}
|
||||
|
||||
bool saved_lr_;
|
||||
};
|
||||
|
||||
Zone* zone_;
|
||||
EhFrameWriter eh_frame_writer_;
|
||||
bool saved_lr_;
|
||||
bool block_will_exit_;
|
||||
|
||||
ZoneVector<const BlockInitialState*> block_initial_states_;
|
||||
};
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_COMPILER_BACKEND_PPC_UNWINDING_INFO_WRITER_PPC_H_
|
@ -168,7 +168,8 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
|
||||
public:
|
||||
OutOfLineRecordWrite(CodeGenerator* gen, Register object, Register offset,
|
||||
Register value, Register scratch0, Register scratch1,
|
||||
RecordWriteMode mode, StubCallMode stub_mode)
|
||||
RecordWriteMode mode, StubCallMode stub_mode,
|
||||
UnwindingInfoWriter* unwinding_info_writer)
|
||||
: OutOfLineCode(gen),
|
||||
object_(object),
|
||||
offset_(offset),
|
||||
@ -179,11 +180,13 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
|
||||
mode_(mode),
|
||||
stub_mode_(stub_mode),
|
||||
must_save_lr_(!gen->frame_access_state()->has_frame()),
|
||||
unwinding_info_writer_(unwinding_info_writer),
|
||||
zone_(gen->zone()) {}
|
||||
|
||||
OutOfLineRecordWrite(CodeGenerator* gen, Register object, int32_t offset,
|
||||
Register value, Register scratch0, Register scratch1,
|
||||
RecordWriteMode mode, StubCallMode stub_mode)
|
||||
RecordWriteMode mode, StubCallMode stub_mode,
|
||||
UnwindingInfoWriter* unwinding_info_writer)
|
||||
: OutOfLineCode(gen),
|
||||
object_(object),
|
||||
offset_(no_reg),
|
||||
@ -194,6 +197,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
|
||||
mode_(mode),
|
||||
stub_mode_(stub_mode),
|
||||
must_save_lr_(!gen->frame_access_state()->has_frame()),
|
||||
unwinding_info_writer_(unwinding_info_writer),
|
||||
zone_(gen->zone()) {}
|
||||
|
||||
void Generate() final {
|
||||
@ -217,6 +221,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
|
||||
if (must_save_lr_) {
|
||||
// We need to save and restore r14 if the frame was elided.
|
||||
__ Push(r14);
|
||||
unwinding_info_writer_->MarkLinkRegisterOnTopOfStack(__ pc_offset());
|
||||
}
|
||||
if (mode_ == RecordWriteMode::kValueIsEphemeronKey) {
|
||||
__ CallEphemeronKeyBarrier(object_, scratch1_, save_fp_mode);
|
||||
@ -230,6 +235,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
|
||||
if (must_save_lr_) {
|
||||
// We need to save and restore r14 if the frame was elided.
|
||||
__ Pop(r14);
|
||||
unwinding_info_writer_->MarkPopLinkRegisterFromTopOfStack(__ pc_offset());
|
||||
}
|
||||
}
|
||||
|
||||
@ -243,6 +249,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
|
||||
RecordWriteMode const mode_;
|
||||
StubCallMode stub_mode_;
|
||||
bool must_save_lr_;
|
||||
UnwindingInfoWriter* const unwinding_info_writer_;
|
||||
Zone* zone_;
|
||||
};
|
||||
|
||||
@ -1164,6 +1171,7 @@ static inline int AssembleUnaryOp(Instruction* instr, _R _r, _M _m, _I _i) {
|
||||
|
||||
void CodeGenerator::AssembleDeconstructFrame() {
|
||||
__ LeaveFrame(StackFrame::MANUAL);
|
||||
unwinding_info_writer_.MarkFrameDeconstructed(__ pc_offset());
|
||||
}
|
||||
|
||||
void CodeGenerator::AssemblePrepareTailCall() {
|
||||
@ -1633,16 +1641,16 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
AddressingModeField::decode(instr->opcode());
|
||||
if (addressing_mode == kMode_MRI) {
|
||||
int32_t offset = i.InputInt32(1);
|
||||
ool = new (zone())
|
||||
OutOfLineRecordWrite(this, object, offset, value, scratch0,
|
||||
scratch1, mode, DetermineStubCallMode());
|
||||
ool = new (zone()) OutOfLineRecordWrite(
|
||||
this, object, offset, value, scratch0, scratch1, mode,
|
||||
DetermineStubCallMode(), &unwinding_info_writer_);
|
||||
__ StoreP(value, MemOperand(object, offset));
|
||||
} else {
|
||||
DCHECK_EQ(kMode_MRR, addressing_mode);
|
||||
Register offset(i.InputRegister(1));
|
||||
ool = new (zone())
|
||||
OutOfLineRecordWrite(this, object, offset, value, scratch0,
|
||||
scratch1, mode, DetermineStubCallMode());
|
||||
ool = new (zone()) OutOfLineRecordWrite(
|
||||
this, object, offset, value, scratch0, scratch1, mode,
|
||||
DetermineStubCallMode(), &unwinding_info_writer_);
|
||||
__ StoreP(value, MemOperand(object, offset));
|
||||
}
|
||||
__ CheckPageFlag(object, scratch0,
|
||||
@ -3113,6 +3121,7 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
}
|
||||
}
|
||||
}
|
||||
unwinding_info_writer_.MarkFrameConstructed(__ pc_offset());
|
||||
}
|
||||
|
||||
int required_slots =
|
||||
@ -3217,6 +3226,8 @@ void CodeGenerator::AssembleReturn(InstructionOperand* pop) {
|
||||
__ MultiPopDoubles(double_saves);
|
||||
}
|
||||
|
||||
unwinding_info_writer_.MarkBlockWillExit();
|
||||
|
||||
S390OperandConverter g(this, nullptr);
|
||||
if (call_descriptor->IsCFunctionCall()) {
|
||||
AssembleDeconstructFrame();
|
||||
|
103
src/compiler/backend/s390/unwinding-info-writer-s390.cc
Normal file
103
src/compiler/backend/s390/unwinding-info-writer-s390.cc
Normal file
@ -0,0 +1,103 @@
|
||||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/compiler/backend/s390/unwinding-info-writer-s390.h"
|
||||
#include "src/compiler/backend/instruction.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
void UnwindingInfoWriter::BeginInstructionBlock(int pc_offset,
|
||||
const InstructionBlock* block) {
|
||||
if (!enabled()) return;
|
||||
|
||||
block_will_exit_ = false;
|
||||
|
||||
DCHECK_LT(block->rpo_number().ToInt(),
|
||||
static_cast<int>(block_initial_states_.size()));
|
||||
const BlockInitialState* initial_state =
|
||||
block_initial_states_[block->rpo_number().ToInt()];
|
||||
if (!initial_state) return;
|
||||
if (initial_state->saved_lr_ != saved_lr_) {
|
||||
eh_frame_writer_.AdvanceLocation(pc_offset);
|
||||
if (initial_state->saved_lr_) {
|
||||
eh_frame_writer_.RecordRegisterSavedToStack(r14, kSystemPointerSize);
|
||||
eh_frame_writer_.RecordRegisterSavedToStack(fp, 0);
|
||||
} else {
|
||||
eh_frame_writer_.RecordRegisterFollowsInitialRule(r14);
|
||||
}
|
||||
saved_lr_ = initial_state->saved_lr_;
|
||||
}
|
||||
}
|
||||
|
||||
void UnwindingInfoWriter::EndInstructionBlock(const InstructionBlock* block) {
|
||||
if (!enabled() || block_will_exit_) return;
|
||||
|
||||
for (const RpoNumber& successor : block->successors()) {
|
||||
int successor_index = successor.ToInt();
|
||||
DCHECK_LT(successor_index, static_cast<int>(block_initial_states_.size()));
|
||||
const BlockInitialState* existing_state =
|
||||
block_initial_states_[successor_index];
|
||||
|
||||
// If we already had an entry for this BB, check that the values are the
|
||||
// same we are trying to insert.
|
||||
if (existing_state) {
|
||||
DCHECK_EQ(existing_state->saved_lr_, saved_lr_);
|
||||
} else {
|
||||
block_initial_states_[successor_index] =
|
||||
new (zone_) BlockInitialState(saved_lr_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UnwindingInfoWriter::MarkFrameConstructed(int at_pc) {
|
||||
if (!enabled()) return;
|
||||
|
||||
// Regardless of the type of frame constructed, the relevant part of the
|
||||
// layout is always the one in the diagram:
|
||||
//
|
||||
// | .... | higher addresses
|
||||
// +----------+ ^
|
||||
// | LR | | |
|
||||
// +----------+ | |
|
||||
// | saved FP | | |
|
||||
// +----------+ <-- FP v
|
||||
// | .... | stack growth
|
||||
//
|
||||
// The LR is pushed on the stack, and we can record this fact at the end of
|
||||
// the construction, since the LR itself is not modified in the process.
|
||||
eh_frame_writer_.AdvanceLocation(at_pc);
|
||||
eh_frame_writer_.RecordRegisterSavedToStack(r14, kSystemPointerSize);
|
||||
eh_frame_writer_.RecordRegisterSavedToStack(fp, 0);
|
||||
saved_lr_ = true;
|
||||
}
|
||||
|
||||
void UnwindingInfoWriter::MarkFrameDeconstructed(int at_pc) {
|
||||
if (!enabled()) return;
|
||||
|
||||
// The lr is restored by the last operation in LeaveFrame().
|
||||
eh_frame_writer_.AdvanceLocation(at_pc);
|
||||
eh_frame_writer_.RecordRegisterFollowsInitialRule(r14);
|
||||
saved_lr_ = false;
|
||||
}
|
||||
|
||||
void UnwindingInfoWriter::MarkLinkRegisterOnTopOfStack(int pc_offset) {
|
||||
if (!enabled()) return;
|
||||
|
||||
eh_frame_writer_.AdvanceLocation(pc_offset);
|
||||
eh_frame_writer_.SetBaseAddressRegisterAndOffset(sp, 0);
|
||||
eh_frame_writer_.RecordRegisterSavedToStack(r14, 0);
|
||||
}
|
||||
|
||||
void UnwindingInfoWriter::MarkPopLinkRegisterFromTopOfStack(int pc_offset) {
|
||||
if (!enabled()) return;
|
||||
|
||||
eh_frame_writer_.AdvanceLocation(pc_offset);
|
||||
eh_frame_writer_.SetBaseAddressRegisterAndOffset(fp, 0);
|
||||
eh_frame_writer_.RecordRegisterFollowsInitialRule(r14);
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
73
src/compiler/backend/s390/unwinding-info-writer-s390.h
Normal file
73
src/compiler/backend/s390/unwinding-info-writer-s390.h
Normal file
@ -0,0 +1,73 @@
|
||||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_COMPILER_BACKEND_S390_UNWINDING_INFO_WRITER_S390_H_
|
||||
#define V8_COMPILER_BACKEND_S390_UNWINDING_INFO_WRITER_S390_H_
|
||||
|
||||
#include "src/diagnostics/eh-frame.h"
|
||||
#include "src/flags/flags.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
|
||||
class InstructionBlock;
|
||||
|
||||
class UnwindingInfoWriter {
|
||||
public:
|
||||
explicit UnwindingInfoWriter(Zone* zone)
|
||||
: zone_(zone),
|
||||
eh_frame_writer_(zone),
|
||||
saved_lr_(false),
|
||||
block_will_exit_(false),
|
||||
block_initial_states_(zone) {
|
||||
if (enabled()) eh_frame_writer_.Initialize();
|
||||
}
|
||||
|
||||
void SetNumberOfInstructionBlocks(int number) {
|
||||
if (enabled()) block_initial_states_.resize(number);
|
||||
}
|
||||
|
||||
void BeginInstructionBlock(int pc_offset, const InstructionBlock* block);
|
||||
void EndInstructionBlock(const InstructionBlock* block);
|
||||
|
||||
void MarkLinkRegisterOnTopOfStack(int pc_offset);
|
||||
void MarkPopLinkRegisterFromTopOfStack(int pc_offset);
|
||||
|
||||
void MarkFrameConstructed(int at_pc);
|
||||
void MarkFrameDeconstructed(int at_pc);
|
||||
|
||||
void MarkBlockWillExit() { block_will_exit_ = true; }
|
||||
|
||||
void Finish(int code_size) {
|
||||
if (enabled()) eh_frame_writer_.Finish(code_size);
|
||||
}
|
||||
|
||||
EhFrameWriter* eh_frame_writer() {
|
||||
return enabled() ? &eh_frame_writer_ : nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
bool enabled() const { return FLAG_perf_prof_unwinding_info; }
|
||||
|
||||
class BlockInitialState : public ZoneObject {
|
||||
public:
|
||||
explicit BlockInitialState(bool saved_lr) : saved_lr_(saved_lr) {}
|
||||
|
||||
bool saved_lr_;
|
||||
};
|
||||
|
||||
Zone* zone_;
|
||||
EhFrameWriter eh_frame_writer_;
|
||||
bool saved_lr_;
|
||||
bool block_will_exit_;
|
||||
|
||||
ZoneVector<const BlockInitialState*> block_initial_states_;
|
||||
};
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_COMPILER_BACKEND_S390_UNWINDING_INFO_WRITER_S390_H_
|
@ -13,6 +13,10 @@
|
||||
#include "src/compiler/backend/arm64/unwinding-info-writer-arm64.h"
|
||||
#elif V8_TARGET_ARCH_X64
|
||||
#include "src/compiler/backend/x64/unwinding-info-writer-x64.h"
|
||||
#elif V8_TARGET_ARCH_S390X
|
||||
#include "src/compiler/backend/s390/unwinding-info-writer-s390.h"
|
||||
#elif V8_TARGET_ARCH_PPC64
|
||||
#include "src/compiler/backend/ppc/unwinding-info-writer-ppc.h"
|
||||
#else
|
||||
|
||||
// Placeholder for unsupported architectures.
|
||||
|
@ -9,8 +9,9 @@
|
||||
|
||||
#include "src/codegen/code-desc.h"
|
||||
|
||||
#if !defined(V8_TARGET_ARCH_X64) && !defined(V8_TARGET_ARCH_ARM) && \
|
||||
!defined(V8_TARGET_ARCH_ARM64)
|
||||
#if !defined(V8_TARGET_ARCH_X64) && !defined(V8_TARGET_ARCH_ARM) && \
|
||||
!defined(V8_TARGET_ARCH_ARM64) && !defined(V8_TARGET_ARCH_S390X) && \
|
||||
!defined(V8_TARGET_ARCH_PPC64)
|
||||
|
||||
// Placeholders for unsupported architectures.
|
||||
|
||||
@ -303,36 +304,44 @@ void EhFrameWriter::SetBaseAddressRegisterAndOffset(Register base_register,
|
||||
base_register_ = base_register;
|
||||
}
|
||||
|
||||
void EhFrameWriter::RecordRegisterSavedToStack(int register_code, int offset) {
|
||||
void EhFrameWriter::RecordRegisterSavedToStack(int dwarf_register_code,
|
||||
int offset) {
|
||||
DCHECK_EQ(writer_state_, InternalState::kInitialized);
|
||||
DCHECK_EQ(offset % EhFrameConstants::kDataAlignmentFactor, 0);
|
||||
int factored_offset = offset / EhFrameConstants::kDataAlignmentFactor;
|
||||
if (factored_offset >= 0) {
|
||||
DCHECK_LE(register_code, EhFrameConstants::kSavedRegisterMask);
|
||||
DCHECK_LE(dwarf_register_code, EhFrameConstants::kSavedRegisterMask);
|
||||
WriteByte((EhFrameConstants::kSavedRegisterTag
|
||||
<< EhFrameConstants::kSavedRegisterMaskSize) |
|
||||
(register_code & EhFrameConstants::kSavedRegisterMask));
|
||||
(dwarf_register_code & EhFrameConstants::kSavedRegisterMask));
|
||||
WriteULeb128(factored_offset);
|
||||
} else {
|
||||
WriteOpcode(EhFrameConstants::DwarfOpcodes::kOffsetExtendedSf);
|
||||
WriteULeb128(register_code);
|
||||
WriteULeb128(dwarf_register_code);
|
||||
WriteSLeb128(factored_offset);
|
||||
}
|
||||
}
|
||||
|
||||
void EhFrameWriter::RecordRegisterNotModified(Register name) {
|
||||
RecordRegisterNotModified(RegisterToDwarfCode(name));
|
||||
}
|
||||
|
||||
void EhFrameWriter::RecordRegisterNotModified(int dwarf_register_code) {
|
||||
DCHECK_EQ(writer_state_, InternalState::kInitialized);
|
||||
WriteOpcode(EhFrameConstants::DwarfOpcodes::kSameValue);
|
||||
WriteULeb128(RegisterToDwarfCode(name));
|
||||
WriteULeb128(dwarf_register_code);
|
||||
}
|
||||
|
||||
void EhFrameWriter::RecordRegisterFollowsInitialRule(Register name) {
|
||||
RecordRegisterFollowsInitialRule(RegisterToDwarfCode(name));
|
||||
}
|
||||
|
||||
void EhFrameWriter::RecordRegisterFollowsInitialRule(int dwarf_register_code) {
|
||||
DCHECK_EQ(writer_state_, InternalState::kInitialized);
|
||||
int code = RegisterToDwarfCode(name);
|
||||
DCHECK_LE(code, EhFrameConstants::kFollowInitialRuleMask);
|
||||
DCHECK_LE(dwarf_register_code, EhFrameConstants::kFollowInitialRuleMask);
|
||||
WriteByte((EhFrameConstants::kFollowInitialRuleTag
|
||||
<< EhFrameConstants::kFollowInitialRuleMaskSize) |
|
||||
(code & EhFrameConstants::kFollowInitialRuleMask));
|
||||
(dwarf_register_code & EhFrameConstants::kFollowInitialRuleMask));
|
||||
}
|
||||
|
||||
void EhFrameWriter::Finish(int code_size) {
|
||||
|
@ -102,11 +102,17 @@ class V8_EXPORT_PRIVATE EhFrameWriter {
|
||||
RecordRegisterSavedToStack(RegisterToDwarfCode(name), offset);
|
||||
}
|
||||
|
||||
// Directly accepts a DWARF register code, needed for
|
||||
// handling pseudo-registers on some platforms.
|
||||
void RecordRegisterSavedToStack(int dwarf_register_code, int offset);
|
||||
|
||||
// The register has not been modified from the previous frame.
|
||||
void RecordRegisterNotModified(Register name);
|
||||
void RecordRegisterNotModified(int dwarf_register_code);
|
||||
|
||||
// The register follows the rule defined in the CIE.
|
||||
void RecordRegisterFollowsInitialRule(Register name);
|
||||
void RecordRegisterFollowsInitialRule(int dwarf_register_code);
|
||||
|
||||
void Finish(int code_size);
|
||||
|
||||
@ -169,10 +175,6 @@ class V8_EXPORT_PRIVATE EhFrameWriter {
|
||||
// Write nops until the size reaches a multiple of 8 bytes.
|
||||
void WritePaddingToAlignedSize(int unpadded_size);
|
||||
|
||||
// Internal version that directly accepts a DWARF register code, needed for
|
||||
// handling pseudo-registers on some platforms.
|
||||
void RecordRegisterSavedToStack(int register_code, int offset);
|
||||
|
||||
int GetProcedureAddressOffset() const {
|
||||
return fde_offset() + EhFrameConstants::kProcedureAddressOffsetInFde;
|
||||
}
|
||||
|
@ -79,6 +79,8 @@ class PerfJitLogger : public CodeEventLogger {
|
||||
static const uint32_t kElfMachARM = 40;
|
||||
static const uint32_t kElfMachMIPS = 10;
|
||||
static const uint32_t kElfMachARM64 = 183;
|
||||
static const uint32_t kElfMachS390x = 22;
|
||||
static const uint32_t kElfMachPPC64 = 21;
|
||||
|
||||
uint32_t GetElfMach() {
|
||||
#if V8_TARGET_ARCH_IA32
|
||||
@ -91,6 +93,10 @@ class PerfJitLogger : public CodeEventLogger {
|
||||
return kElfMachMIPS;
|
||||
#elif V8_TARGET_ARCH_ARM64
|
||||
return kElfMachARM64;
|
||||
#elif V8_TARGET_ARCH_S390X
|
||||
return kElfMachS390x;
|
||||
#elif V8_TARGET_ARCH_PPC64
|
||||
return kElfMachPPC64;
|
||||
#else
|
||||
UNIMPLEMENTED();
|
||||
return 0;
|
||||
|
57
src/diagnostics/ppc/eh-frame-ppc.cc
Normal file
57
src/diagnostics/ppc/eh-frame-ppc.cc
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/codegen/ppc/constants-ppc.h"
|
||||
#include "src/diagnostics/eh-frame.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
const int EhFrameConstants::kCodeAlignmentFactor = 4;
|
||||
// all PPC are 4 bytes instruction
|
||||
const int EhFrameConstants::kDataAlignmentFactor = -8; // 64-bit always -8
|
||||
|
||||
void EhFrameWriter::WriteReturnAddressRegisterCode() {
|
||||
WriteULeb128(kLrDwarfCode);
|
||||
}
|
||||
|
||||
void EhFrameWriter::WriteInitialStateInCie() {
|
||||
SetBaseAddressRegisterAndOffset(fp, 0);
|
||||
RecordRegisterNotModified(kLrDwarfCode);
|
||||
}
|
||||
|
||||
// static
|
||||
int EhFrameWriter::RegisterToDwarfCode(Register name) {
|
||||
switch (name.code()) {
|
||||
case kRegCode_fp:
|
||||
return kFpDwarfCode;
|
||||
case kRegCode_sp:
|
||||
return kSpDwarfCode;
|
||||
case kRegCode_r0:
|
||||
return kR0DwarfCode;
|
||||
default:
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_DISASSEMBLER
|
||||
|
||||
// static
|
||||
const char* EhFrameDisassembler::DwarfRegisterCodeToString(int code) {
|
||||
switch (code) {
|
||||
case kFpDwarfCode:
|
||||
return "fp";
|
||||
case kSpDwarfCode:
|
||||
return "sp";
|
||||
default:
|
||||
UNIMPLEMENTED();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
65
src/diagnostics/s390/eh-frame-s390.cc
Normal file
65
src/diagnostics/s390/eh-frame-s390.cc
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/codegen/s390/assembler-s390-inl.h"
|
||||
#include "src/diagnostics/eh-frame.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
static const int kR0DwarfCode = 0;
|
||||
static const int kFpDwarfCode = 11; // frame-pointer
|
||||
static const int kR14DwarfCode = 14; // return-address(lr)
|
||||
static const int kSpDwarfCode = 15; // stack-pointer
|
||||
|
||||
const int EhFrameConstants::kCodeAlignmentFactor = 2; // 1 or 2 in s390
|
||||
const int EhFrameConstants::kDataAlignmentFactor = -8;
|
||||
|
||||
void EhFrameWriter::WriteReturnAddressRegisterCode() {
|
||||
WriteULeb128(kR14DwarfCode);
|
||||
}
|
||||
|
||||
void EhFrameWriter::WriteInitialStateInCie() {
|
||||
SetBaseAddressRegisterAndOffset(fp, 0);
|
||||
RecordRegisterNotModified(r14);
|
||||
}
|
||||
|
||||
// static
|
||||
int EhFrameWriter::RegisterToDwarfCode(Register name) {
|
||||
switch (name.code()) {
|
||||
case kRegCode_fp:
|
||||
return kFpDwarfCode;
|
||||
case kRegCode_r14:
|
||||
return kR14DwarfCode;
|
||||
case kRegCode_sp:
|
||||
return kSpDwarfCode;
|
||||
case kRegCode_r0:
|
||||
return kR0DwarfCode;
|
||||
default:
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_DISASSEMBLER
|
||||
|
||||
// static
|
||||
const char* EhFrameDisassembler::DwarfRegisterCodeToString(int code) {
|
||||
switch (code) {
|
||||
case kFpDwarfCode:
|
||||
return "fp";
|
||||
case kR14DwarfCode:
|
||||
return "lr";
|
||||
case kSpDwarfCode:
|
||||
return "sp";
|
||||
default:
|
||||
UNIMPLEMENTED();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
Loading…
Reference in New Issue
Block a user