Commit 7b64e8d1 authored by leszeks's avatar leszeks Committed by Commit bot

[ignition/turbofan] Wrap bytecode liveness bitvectors

Wrap the liveness bitvectors from the bytecode liveness analysis with a
helper class, which makes the register/accumulator bits explicit.

Review-Url: https://codereview.chromium.org/2552723004
Cr-Commit-Position: refs/heads/master@{#41589}
parent 98b563eb
......@@ -166,7 +166,7 @@ class BitVector : public ZoneObject {
return true;
}
bool Equals(const BitVector& other) {
bool Equals(const BitVector& other) const {
for (int i = 0; i < data_length_; i++) {
if (data_[i] != other.data_[i]) return false;
}
......
......@@ -27,21 +27,21 @@ BytecodeAnalysis::BytecodeAnalysis(Handle<BytecodeArray> bytecode_array,
namespace {
void UpdateInLiveness(Bytecode bytecode, BitVector& in_liveness,
void UpdateInLiveness(Bytecode bytecode, BytecodeLivenessState& in_liveness,
const BytecodeArrayAccessor& accessor) {
int num_operands = Bytecodes::NumberOfOperands(bytecode);
const OperandType* operand_types = Bytecodes::GetOperandTypes(bytecode);
AccumulatorUse accumulator_use = Bytecodes::GetAccumulatorUse(bytecode);
if (accumulator_use == AccumulatorUse::kWrite) {
in_liveness.Remove(in_liveness.length() - 1);
in_liveness.MarkAccumulatorDead();
}
for (int i = 0; i < num_operands; ++i) {
switch (operand_types[i]) {
case OperandType::kRegOut: {
interpreter::Register r = accessor.GetRegisterOperand(i);
if (!r.is_parameter()) {
in_liveness.Remove(r.index());
in_liveness.MarkRegisterDead(r.index());
}
break;
}
......@@ -49,8 +49,8 @@ void UpdateInLiveness(Bytecode bytecode, BitVector& in_liveness,
interpreter::Register r = accessor.GetRegisterOperand(i);
if (!r.is_parameter()) {
DCHECK(!interpreter::Register(r.index() + 1).is_parameter());
in_liveness.Remove(r.index());
in_liveness.Remove(r.index() + 1);
in_liveness.MarkRegisterDead(r.index());
in_liveness.MarkRegisterDead(r.index() + 1);
}
break;
}
......@@ -59,9 +59,9 @@ void UpdateInLiveness(Bytecode bytecode, BitVector& in_liveness,
if (!r.is_parameter()) {
DCHECK(!interpreter::Register(r.index() + 1).is_parameter());
DCHECK(!interpreter::Register(r.index() + 2).is_parameter());
in_liveness.Remove(r.index());
in_liveness.Remove(r.index() + 1);
in_liveness.Remove(r.index() + 2);
in_liveness.MarkRegisterDead(r.index());
in_liveness.MarkRegisterDead(r.index() + 1);
in_liveness.MarkRegisterDead(r.index() + 2);
}
break;
}
......@@ -72,14 +72,14 @@ void UpdateInLiveness(Bytecode bytecode, BitVector& in_liveness,
}
if (accumulator_use == AccumulatorUse::kRead) {
in_liveness.Add(in_liveness.length() - 1);
in_liveness.MarkAccumulatorLive();
}
for (int i = 0; i < num_operands; ++i) {
switch (operand_types[i]) {
case OperandType::kReg: {
interpreter::Register r = accessor.GetRegisterOperand(i);
if (!r.is_parameter()) {
in_liveness.Add(r.index());
in_liveness.MarkRegisterLive(r.index());
}
break;
}
......@@ -87,8 +87,8 @@ void UpdateInLiveness(Bytecode bytecode, BitVector& in_liveness,
interpreter::Register r = accessor.GetRegisterOperand(i);
if (!r.is_parameter()) {
DCHECK(!interpreter::Register(r.index() + 1).is_parameter());
in_liveness.Add(r.index());
in_liveness.Add(r.index() + 1);
in_liveness.MarkRegisterLive(r.index());
in_liveness.MarkRegisterLive(r.index() + 1);
}
break;
}
......@@ -98,7 +98,7 @@ void UpdateInLiveness(Bytecode bytecode, BitVector& in_liveness,
if (!r.is_parameter()) {
for (uint32_t j = 0; j < reg_count; ++j) {
DCHECK(!interpreter::Register(r.index() + j).is_parameter());
in_liveness.Add(r.index() + j);
in_liveness.MarkRegisterLive(r.index() + j);
}
}
}
......@@ -109,8 +109,8 @@ void UpdateInLiveness(Bytecode bytecode, BitVector& in_liveness,
}
}
void UpdateOutLiveness(Bytecode bytecode, BitVector& out_liveness,
BitVector* next_bytecode_in_liveness,
void UpdateOutLiveness(Bytecode bytecode, BytecodeLivenessState& out_liveness,
BytecodeLivenessState* next_bytecode_in_liveness,
const BytecodeArrayAccessor& accessor,
const BytecodeLivenessMap& liveness_map) {
int current_offset = accessor.current_offset();
......@@ -140,7 +140,7 @@ void UpdateOutLiveness(Bytecode bytecode, BitVector& out_liveness,
if (handler_offset != -1) {
out_liveness.Union(*liveness_map.GetInLiveness(handler_offset));
out_liveness.Add(handler_context);
out_liveness.MarkRegisterLive(handler_context);
}
}
}
......@@ -150,7 +150,7 @@ void UpdateOutLiveness(Bytecode bytecode, BitVector& out_liveness,
void BytecodeAnalysis::Analyze() {
loop_stack_.push(-1);
BitVector* next_bytecode_in_liveness = nullptr;
BytecodeLivenessState* next_bytecode_in_liveness = nullptr;
BytecodeArrayRandomIterator iterator(bytecode_array(), zone());
for (iterator.GoToEnd(); iterator.IsValid(); --iterator) {
......@@ -172,10 +172,8 @@ void BytecodeAnalysis::Analyze() {
}
if (do_liveness_analysis_) {
// The liveness vector had bits for the liveness of the registers, and one
// more bit for the liveness of the accumulator.
Liveness& liveness = liveness_map_.InitializeLiveness(
current_offset, bytecode_array()->register_count() + 1, zone());
BytecodeLiveness& liveness = liveness_map_.InitializeLiveness(
current_offset, bytecode_array()->register_count(), zone());
UpdateOutLiveness(bytecode, *liveness.out, next_bytecode_in_liveness,
iterator, liveness_map_);
......@@ -224,8 +222,9 @@ void BytecodeAnalysis::Analyze() {
int header_offset = iterator.GetJumpTargetOffset();
int end_offset = iterator.current_offset();
Liveness& header_liveness = liveness_map_.GetLiveness(header_offset);
Liveness& end_liveness = liveness_map_.GetLiveness(end_offset);
BytecodeLiveness& header_liveness =
liveness_map_.GetLiveness(header_offset);
BytecodeLiveness& end_liveness = liveness_map_.GetLiveness(end_offset);
if (!end_liveness.out->UnionIsChanged(*header_liveness.in)) {
// Only update the loop body if the loop end liveness changed.
......@@ -240,7 +239,7 @@ void BytecodeAnalysis::Analyze() {
Bytecode bytecode = iterator.current_bytecode();
int current_offset = iterator.current_offset();
Liveness& liveness = liveness_map_.GetLiveness(current_offset);
BytecodeLiveness& liveness = liveness_map_.GetLiveness(current_offset);
UpdateOutLiveness(bytecode, *liveness.out, next_bytecode_in_liveness,
iterator, liveness_map_);
......@@ -313,13 +312,15 @@ int BytecodeAnalysis::GetParentLoopFor(int header_offset) const {
return header_to_parent_.find(header_offset)->second;
}
const BitVector* BytecodeAnalysis::GetInLivenessFor(int offset) const {
const BytecodeLivenessState* BytecodeAnalysis::GetInLivenessFor(
int offset) const {
if (!do_liveness_analysis_) return nullptr;
return liveness_map_.GetInLiveness(offset);
}
const BitVector* BytecodeAnalysis::GetOutLivenessFor(int offset) const {
const BytecodeLivenessState* BytecodeAnalysis::GetOutLivenessFor(
int offset) const {
if (!do_liveness_analysis_) return nullptr;
return liveness_map_.GetOutLiveness(offset);
......@@ -331,16 +332,18 @@ std::ostream& BytecodeAnalysis::PrintLivenessTo(std::ostream& os) const {
for (; !iterator.done(); iterator.Advance()) {
int current_offset = iterator.current_offset();
const BitVector* in_liveness = GetInLivenessFor(current_offset);
const BitVector* out_liveness = GetOutLivenessFor(current_offset);
const BitVector& in_liveness =
GetInLivenessFor(current_offset)->bit_vector();
const BitVector& out_liveness =
GetOutLivenessFor(current_offset)->bit_vector();
for (int i = 0; i < in_liveness->length(); ++i) {
os << (in_liveness->Contains(i) ? "L" : ".");
for (int i = 0; i < in_liveness.length(); ++i) {
os << (in_liveness.Contains(i) ? "L" : ".");
}
os << " -> ";
for (int i = 0; i < out_liveness->length(); ++i) {
os << (out_liveness->Contains(i) ? "L" : ".");
for (int i = 0; i < out_liveness.length(); ++i) {
os << (out_liveness.Contains(i) ? "L" : ".");
}
os << " | " << current_offset << ": ";
......@@ -354,12 +357,13 @@ std::ostream& BytecodeAnalysis::PrintLivenessTo(std::ostream& os) const {
bool BytecodeAnalysis::LivenessIsValid() {
BytecodeArrayRandomIterator iterator(bytecode_array(), zone());
BitVector previous_liveness(bytecode_array()->register_count() + 1, zone());
BytecodeLivenessState previous_liveness(bytecode_array()->register_count(),
zone());
int invalid_offset = -1;
int which_invalid = -1;
BitVector* next_bytecode_in_liveness = nullptr;
BytecodeLivenessState* next_bytecode_in_liveness = nullptr;
// Ensure that there are no liveness changes if we iterate one more time.
for (iterator.GoToEnd(); iterator.IsValid(); --iterator) {
......@@ -367,7 +371,7 @@ bool BytecodeAnalysis::LivenessIsValid() {
int current_offset = iterator.current_offset();
Liveness& liveness = liveness_map_.GetLiveness(current_offset);
BytecodeLiveness& liveness = liveness_map_.GetLiveness(current_offset);
previous_liveness.CopyFrom(*liveness.out);
......@@ -414,17 +418,19 @@ bool BytecodeAnalysis::LivenessIsValid() {
BytecodeArrayIterator forward_iterator(bytecode_array());
for (; !forward_iterator.done(); forward_iterator.Advance()) {
int current_offset = forward_iterator.current_offset();
BitVector* in_liveness = liveness_map_.GetInLiveness(current_offset);
BitVector* out_liveness = liveness_map_.GetOutLiveness(current_offset);
const BitVector& in_liveness =
GetInLivenessFor(current_offset)->bit_vector();
const BitVector& out_liveness =
GetOutLivenessFor(current_offset)->bit_vector();
for (int i = 0; i < in_liveness->length(); ++i) {
of << (in_liveness->Contains(i) ? 'L' : '.');
for (int i = 0; i < in_liveness.length(); ++i) {
of << (in_liveness.Contains(i) ? 'L' : '.');
}
of << " | ";
for (int i = 0; i < out_liveness->length(); ++i) {
of << (out_liveness->Contains(i) ? 'L' : '.');
for (int i = 0; i < out_liveness.length(); ++i) {
of << (out_liveness.Contains(i) ? 'L' : '.');
}
of << " : " << current_offset << " : ";
......@@ -448,14 +454,14 @@ bool BytecodeAnalysis::LivenessIsValid() {
if (current_offset == invalid_offset) {
// Underline the invalid liveness.
if (which_invalid == 0) {
for (int i = 0; i < in_liveness->length(); ++i) {
for (int i = 0; i < in_liveness.length(); ++i) {
of << '^';
}
} else {
for (int i = 0; i < in_liveness->length() + 3; ++i) {
for (int i = 0; i < in_liveness.length() + 3; ++i) {
of << ' ';
}
for (int i = 0; i < out_liveness->length(); ++i) {
for (int i = 0; i < out_liveness.length(); ++i) {
of << '^';
}
}
......
......@@ -36,17 +36,11 @@ class V8_EXPORT_PRIVATE BytecodeAnalysis BASE_EMBEDDED {
// at {header_offset}, or -1 for outer-most loops.
int GetParentLoopFor(int header_offset) const;
// Gets the in-liveness for the bytecode at {offset}. The liveness bit vector
// represents the liveness of the registers and the accumulator, with the last
// bit being the accumulator liveness bit, and so is (register count + 1) bits
// long.
const BitVector* GetInLivenessFor(int offset) const;
// Gets the out-liveness for the bytecode at {offset}. The liveness bit vector
// represents the liveness of the registers and the accumulator, with the last
// bit being the accumulator liveness bit, and so is (register count + 1) bits
// long.
const BitVector* GetOutLivenessFor(int offset) const;
// Gets the in-liveness for the bytecode at {offset}.
const BytecodeLivenessState* GetInLivenessFor(int offset) const;
// Gets the out-liveness for the bytecode at {offset}.
const BytecodeLivenessState* GetOutLivenessFor(int offset) const;
std::ostream& PrintLivenessTo(std::ostream& os) const;
......
......@@ -56,7 +56,8 @@ class BytecodeGraphBuilder::Environment : public ZoneObject {
// Preserve a checkpoint of the environment for the IR graph. Any
// further mutation of the environment will not affect checkpoints.
Node* Checkpoint(BailoutId bytecode_offset, OutputFrameStateCombine combine,
bool owner_has_exception, const BitVector* liveness);
bool owner_has_exception,
const BytecodeLivenessState* liveness);
// Control dependency tracked by this environment.
Node* GetControlDependency() const { return control_dependency_; }
......@@ -410,7 +411,7 @@ void BytecodeGraphBuilder::Environment::UpdateStateValuesWithCache(
Node* BytecodeGraphBuilder::Environment::Checkpoint(
BailoutId bailout_id, OutputFrameStateCombine combine,
bool owner_has_exception, const BitVector* liveness) {
bool owner_has_exception, const BytecodeLivenessState* liveness) {
UpdateStateValues(&parameters_state_values_, &values()->at(0),
parameter_count());
......@@ -418,12 +419,12 @@ Node* BytecodeGraphBuilder::Environment::Checkpoint(
Node* optimized_out = builder()->jsgraph()->OptimizedOutConstant();
for (int i = 0; i < register_count(); ++i) {
state_value_working_area_[i] = liveness->Contains(i)
state_value_working_area_[i] = liveness->RegisterIsLive(i)
? values()->at(register_base() + i)
: optimized_out;
}
Node* accumulator_value = liveness->Contains(register_count())
Node* accumulator_value = liveness->AccumulatorIsLive()
? values()->at(accumulator_base())
: optimized_out;
......@@ -570,7 +571,8 @@ void BytecodeGraphBuilder::PrepareEagerCheckpoint() {
NodeProperties::GetFrameStateInput(node)->opcode());
BailoutId bailout_id(bytecode_iterator().current_offset());
const BitVector* liveness_before = bytecode_analysis()->GetInLivenessFor(
const BytecodeLivenessState* liveness_before =
bytecode_analysis()->GetInLivenessFor(
bytecode_iterator().current_offset());
Node* frame_state_before = environment()->Checkpoint(
......@@ -590,7 +592,8 @@ void BytecodeGraphBuilder::PrepareFrameState(Node* node,
BailoutId bailout_id(bytecode_iterator().current_offset());
bool has_exception = NodeProperties::IsExceptionalCall(node);
const BitVector* liveness_after = bytecode_analysis()->GetOutLivenessFor(
const BytecodeLivenessState* liveness_after =
bytecode_analysis()->GetOutLivenessFor(
bytecode_iterator().current_offset());
Node* frame_state_after = environment()->Checkpoint(
......
......@@ -8,9 +8,9 @@ namespace v8 {
namespace internal {
namespace compiler {
Liveness::Liveness(int size, Zone* zone)
: in(new (zone) BitVector(size, zone)),
out(new (zone) BitVector(size, zone)) {}
BytecodeLiveness::BytecodeLiveness(int register_count, Zone* zone)
: in(new (zone) BytecodeLivenessState(register_count, zone)),
out(new (zone) BytecodeLivenessState(register_count, zone)) {}
BytecodeLivenessMap::BytecodeLivenessMap(int bytecode_size, Zone* zone)
: liveness_map_(base::bits::RoundUpToPowerOfTwo32(bytecode_size / 4 + 1),
......@@ -19,20 +19,21 @@ BytecodeLivenessMap::BytecodeLivenessMap(int bytecode_size, Zone* zone)
uint32_t OffsetHash(int offset) { return offset; }
Liveness& BytecodeLivenessMap::InitializeLiveness(int offset, int size,
BytecodeLiveness& BytecodeLivenessMap::InitializeLiveness(int offset,
int register_count,
Zone* zone) {
return liveness_map_
.LookupOrInsert(offset, OffsetHash(offset),
[&]() { return Liveness(size, zone); },
[&]() { return BytecodeLiveness(register_count, zone); },
ZoneAllocationPolicy(zone))
->value;
}
Liveness& BytecodeLivenessMap::GetLiveness(int offset) {
BytecodeLiveness& BytecodeLivenessMap::GetLiveness(int offset) {
return liveness_map_.Lookup(offset, OffsetHash(offset))->value;
}
const Liveness& BytecodeLivenessMap::GetLiveness(int offset) const {
const BytecodeLiveness& BytecodeLivenessMap::GetLiveness(int offset) const {
return liveness_map_.Lookup(offset, OffsetHash(offset))->value;
}
......
......@@ -16,35 +16,99 @@ class Zone;
namespace compiler {
struct Liveness {
BitVector* in;
BitVector* out;
class BytecodeLivenessState : public ZoneObject {
public:
BytecodeLivenessState(int register_count, Zone* zone)
: bit_vector_(register_count + 1, zone) {}
const BitVector& bit_vector() const { return bit_vector_; }
BitVector& bit_vector() { return bit_vector_; }
bool RegisterIsLive(int index) const {
DCHECK_GE(index, 0);
DCHECK_LT(index, bit_vector_.length() - 1);
return bit_vector_.Contains(index);
}
bool AccumulatorIsLive() const {
return bit_vector_.Contains(bit_vector_.length() - 1);
}
bool Equals(const BytecodeLivenessState& other) const {
return bit_vector_.Equals(other.bit_vector_);
}
void MarkRegisterLive(int index) {
DCHECK_GE(index, 0);
DCHECK_LT(index, bit_vector_.length() - 1);
bit_vector_.Add(index);
}
void MarkRegisterDead(int index) {
DCHECK_GE(index, 0);
DCHECK_LT(index, bit_vector_.length() - 1);
bit_vector_.Remove(index);
}
void MarkAccumulatorLive() { bit_vector_.Add(bit_vector_.length() - 1); }
void MarkAccumulatorDead() { bit_vector_.Remove(bit_vector_.length() - 1); }
void MarkAllLive() { bit_vector_.AddAll(); }
Liveness(int size, Zone* zone);
void Union(const BytecodeLivenessState& other) {
bit_vector_.Union(other.bit_vector_);
}
bool UnionIsChanged(const BytecodeLivenessState& other) {
return bit_vector_.UnionIsChanged(other.bit_vector_);
}
void CopyFrom(const BytecodeLivenessState& other) {
bit_vector_.CopyFrom(other.bit_vector_);
}
private:
BitVector bit_vector_;
DISALLOW_COPY_AND_ASSIGN(BytecodeLivenessState);
};
struct BytecodeLiveness {
BytecodeLivenessState* in;
BytecodeLivenessState* out;
BytecodeLiveness(int register_count, Zone* zone);
};
class V8_EXPORT_PRIVATE BytecodeLivenessMap {
public:
BytecodeLivenessMap(int size, Zone* zone);
Liveness& InitializeLiveness(int offset, int size, Zone* zone);
BytecodeLiveness& InitializeLiveness(int offset, int register_count,
Zone* zone);
Liveness& GetLiveness(int offset);
const Liveness& GetLiveness(int offset) const;
BytecodeLiveness& GetLiveness(int offset);
const BytecodeLiveness& GetLiveness(int offset) const;
BitVector* GetInLiveness(int offset) { return GetLiveness(offset).in; }
const BitVector* GetInLiveness(int offset) const {
BytecodeLivenessState* GetInLiveness(int offset) {
return GetLiveness(offset).in;
}
const BytecodeLivenessState* GetInLiveness(int offset) const {
return GetLiveness(offset).in;
}
BitVector* GetOutLiveness(int offset) { return GetLiveness(offset).out; }
const BitVector* GetOutLiveness(int offset) const {
BytecodeLivenessState* GetOutLiveness(int offset) {
return GetLiveness(offset).out;
}
const BytecodeLivenessState* GetOutLiveness(int offset) const {
return GetLiveness(offset).out;
}
private:
base::TemplateHashMapImpl<int, Liveness, base::KeyEqualityMatcher<int>,
ZoneAllocationPolicy>
base::TemplateHashMapImpl<int, BytecodeLiveness,
base::KeyEqualityMatcher<int>, ZoneAllocationPolicy>
liveness_map_;
};
......
......@@ -37,11 +37,13 @@ class BytecodeAnalysisTest : public TestWithIsolateAndZone {
i::FLAG_ignition_reo = old_FLAG_ignition_reo_;
}
std::string ToLivenessString(const BitVector* liveness) const {
std::string ToLivenessString(const BytecodeLivenessState* liveness) const {
const BitVector& bit_vector = liveness->bit_vector();
std::string out;
out.resize(liveness->length());
for (int i = 0; i < liveness->length(); ++i) {
if (liveness->Contains(i)) {
out.resize(bit_vector.length());
for (int i = 0; i < bit_vector.length(); ++i) {
if (bit_vector.Contains(i)) {
out[i] = 'L';
} else {
out[i] = '.';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment